/home/caleb/ASDV-Java/Semester 3/Assignments/MP5-Binary-Files_CalebFontenot/src/com/calebfontenot/mp5/files_calebfontenot/CombineFilesFX.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 java.io.DataInput;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.stage.FileChooser;
import javafx.stage.Stage;

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

    static ArrayList<File> files = new ArrayList<File>();
    final FileChooser fileChooser = new FileChooser();

    @Override
    public void start(final Stage stage) throws Exception {
        fileChooser.setTitle("Open File to Split...");
        BorderPane primaryBorderPane = new BorderPane();
        GridPane textFieldGridPane = new GridPane();

        Label infoLabel = new Label("Point me at the files that were output by SplitFilesFX.java.");
        Label chooseFile = new Label("Choose files to combine: ");
        Button openFilePicker = new Button("Choose...");
        Button run = new Button("Start");
        textFieldGridPane.add(chooseFile, 0, 0);
        textFieldGridPane.add(openFilePicker, 1, 0);
        primaryBorderPane.setAlignment(run, Pos.CENTER);

        primaryBorderPane.setTop(infoLabel);
        primaryBorderPane.setCenter(textFieldGridPane);
        primaryBorderPane.setBottom(run);

        openFilePicker.setOnAction(e -> {
            // When we initially get the files from the file chooser, it returns an unsortable list. Because of this, we need to create a new List with its data.
            files.addAll(fileChooser.showOpenMultipleDialog(openFilePicker.getScene().getWindow()));
            // The file picker appears to return files in a random order, so we need to sort them by file name.
            Collections.sort(files, new Comparator<File>() {
                public int compare(File o1, File o2) {
                    return extractInt(o1.getName()) - extractInt(o2.getName());
                }

                String findMatch(String s) {
                    Pattern findNum = Pattern.compile("\\d+$");
                    Matcher match = findNum.matcher(s);
                    while (match.find()) {
                        return match.group();
                    }
                    return "";
                }

                int extractInt(String s) {
                    String num = findMatch(s);
                    System.out.println(num);
                    // return 0 if no digits found
                    return num.isEmpty() ? 0 : Integer.parseInt(num);
                }
            });
        });

        run.setOnAction(e -> {
            if (files == null) {
                e.consume();
            }
            combineFiles(files);
        });

        Scene scene = new Scene(primaryBorderPane);
        stage.setScene(scene);
        stage.show();
    }

    public static void combineFiles(List<File> filesToCombine) {
        String outputPath = filesToCombine.get(0).getParent();
        try (FileOutputStream dataOut = new FileOutputStream(outputPath + "/" + "reconstructed_" + filesToCombine.get(0).getName().substring(0, (filesToCombine.get(0).getName().length() - 2)))) {
            System.out.println("Writing to " + outputPath + "/" + "reconstructed_" + filesToCombine.get(0).getName().substring(0, (filesToCombine.get(0).getName().length() - 2)));
            for (File file : filesToCombine) {
                try (FileInputStream dataIn = new FileInputStream(file)) {
                    System.out.println("Opening the source file " + file.getName() + "!");
                    byte[] buffer = new byte[4096];
                    int bytesRead = -1;

                    while ((bytesRead = dataIn.read(buffer)) != -1) {
                        dataOut.write(buffer, 0, bytesRead);
                    }
                }
            catch (IOException ex) {
            System.out.println(ex);
        }
            }
        } catch (IOException ex) {
            System.out.println(ex);
        }
            Alert alert = new Alert(AlertType.INFORMATION);
            alert.setTitle("Success!");
            alert.setContentText("Successfully combined the files!");

            alert.showAndWait();
        }

    

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