/home/caleb/ASDV-Java/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/src/com/calebfontenot/mp5/files_calebfontenot/HexEditorFX.java
/*
 * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
 * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
 */
package com.calebfontenot.mp5.files_calebfontenot;

import static com.calebfontenot.mp5.files_calebfontenot.SplitFilesFX.alert;
import static com.calebfontenot.mp5.files_calebfontenot.SplitFilesFX.file;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.stage.FileChooser;
import javafx.stage.Stage;

/**
 *
 * @author caleb
 */
public class HexEditorFX extends Application {

    final FileChooser fileChooser = new FileChooser();
    static File file = null;

    @Override
    public void start(Stage stage) throws Exception {
        Label label = new Label("Open a file...");
        Button openFileButton = new Button("Choose...");
        TextArea editorWindow = new TextArea();
        Button saveFileButton = new Button("Save");

        editorWindow.setWrapText(true);

        BorderPane bp = new BorderPane();
        GridPane openFileGridPane = new GridPane();

        openFileGridPane.add(label, 0, 0);
        openFileGridPane.add(openFileButton, 1, 0);

        bp.setTop(openFileGridPane);
        bp.setCenter(editorWindow);
        bp.setBottom(saveFileButton);
        bp.setAlignment(saveFileButton, Pos.CENTER);

        openFileButton.setOnAction(e -> {
            file = fileChooser.showOpenDialog(openFileButton.getScene().getWindow());
            byte[] data = null;
            System.out.println("Getting data from fileand encoding it as hex...");
            try (FileInputStream dataIn = new FileInputStream(file)) {
                data = dataIn.readAllBytes();
            } catch (FileNotFoundException ex) {
                ex.printStackTrace();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
            String dataString = encodeHexString(data);
            editorWindow.setText(dataString);
        });

        saveFileButton.setOnAction(e -> {
            if (file == null) {
                alert.setTitle("No file selected!");
                alert.setHeaderText("No file selected!");
                alert.setContentText("You have to open a file first, silly!");
                alert.showAndWait();
            }
            System.out.println("Re-encoding hex back into a byte array...");

            try (FileOutputStream dataOut = new FileOutputStream(file)) {
                byte[] bytesToSave = decodeHexString(editorWindow.getText());
                dataOut.write(bytesToSave);
            } catch (FileNotFoundException ex) {
                ex.printStackTrace();
            } catch (IOException ex) {
                ex.printStackTrace();
            } catch (IllegalArgumentException ex) {
                alert.setTitle("Invalid Hex!");
                alert.setContentText("Invalid hex entered into the text box, unable to save.");
                alert.showAndWait();
            }
            alert.setTitle("Save successful!");
            alert.setContentText("File saved successfully.");
            alert.showAndWait();
        });

        Scene scene = new Scene(bp);
        stage.setScene(scene);
        stage.show();

    }

    private int toDigit(char hexChar) {
        int digit = Character.digit(hexChar, 16);
        if (digit == -1) {
            throw new IllegalArgumentException(
                    "Invalid Hexadecimal Character: " + hexChar);
        }
        return digit;
    }

    public byte hexToByte(String hexString) {
        int firstDigit = toDigit(hexString.charAt(0));
        int secondDigit = toDigit(hexString.charAt(1));
        return (byte) ((firstDigit << 4) + secondDigit);
    }

    public byte[] decodeHexString(String hexString) {
        if (hexString.length() % 2 == 1) {
            throw new IllegalArgumentException(
                    "Invalid hexadecimal String supplied.");
        }
        byte[] bytes = new byte[hexString.length() / 2];
        for (int i = 0; i < hexString.length(); i += 2) {
            bytes[i / 2] = hexToByte(hexString.substring(i, i + 2));
        }
        return bytes;
    }

    public String byteToHex(byte num) {
        char[] hexDigits = new char[2];
        hexDigits[0] = Character.forDigit((num >> 4) & 0xF, 16);
        hexDigits[1] = Character.forDigit((num & 0xF), 16);
        return new String(hexDigits);
    }

    public String encodeHexString(byte[] byteArray) {
        StringBuffer hexStringBuffer = new StringBuffer();
        for (int i = 0; i < byteArray.length; i++) {
            hexStringBuffer.append(byteToHex(byteArray[i]));
        }
        return hexStringBuffer.toString();
    }

    public static void main(String[] args) {
        launch(args);
    }
}