import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVPrinter;

import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.*;
import java.util.regex.Pattern;

public class PlateFileWriter {
    private int size;
    private List<List<Integer[]>> wells;
    private double stdDev;
    private double lambda;
    private Double error;
    private String filename;
    private String sourceFileName;
    private String[] headers;
    private List<Integer> concentrations;
    private boolean isExponential = false;

    public PlateFileWriter(String filename, Plate plate) {
        if(!filename.matches(".*\\.csv")){
            filename = filename + ".csv";
        }
        this.filename = filename;
        this.sourceFileName = plate.getSourceFileName();
        this.size = plate.getSize();
        this.isExponential = plate.isExponential();
        if(isExponential) {
            this.lambda = plate.getLambda();
        }
        else{
            this.stdDev = plate.getStdDev();
        }
        this.error = plate.getError();
        this.wells = plate.getWells();
        this.concentrations = Arrays.asList(plate.getConcentrations());
        concentrations.sort(Comparator.reverseOrder());
    }

    public void writePlateFile(){
        Comparator<List<Integer[]>> listLengthDescending = Comparator.comparingInt(List::size);
        wells.sort(listLengthDescending.reversed());
        int maxLength = wells.get(0).size();
        List<List<String>> wellsAsStrings = new ArrayList<>();
        for (List<Integer[]> w: wells){
            List<String> tmp = new ArrayList<>();
            for(Integer[] c: w) {
                tmp.add(Arrays.toString(c));
            }
            wellsAsStrings.add(tmp);
        }
        for(List<String> w: wellsAsStrings){
            while(w.size() < maxLength){
                w.add("");
            }
        }

        //this took forever, and I don't use it, because it makes reading data in a huge pain
        List<List<String>> rows = new ArrayList<>();
        List<String> tmp = new ArrayList<>();
        for(int i = 0; i < wellsAsStrings.size(); i++){//List<Integer[]> w: wells){
            tmp.add("well " + (i+1));
        }
        rows.add(tmp);
        for(int row = 0; row < maxLength; row++){
            tmp = new ArrayList<>();
            for(List<String> c: wellsAsStrings){
                tmp.add(c.get(row));
            }
            rows.add(tmp);
        }
        //build string of well concentrations
        StringBuilder concen = new StringBuilder();
        for(Integer i: concentrations){
            concen.append(i.toString());
            concen.append(" ");
        }
        String concenString = concen.toString();

        CSVFormat plateFileFormat = CSVFormat.Builder.create()
                .setCommentMarker('#')
                .build();

        try(BufferedWriter writer = Files.newBufferedWriter(Path.of(filename), StandardOpenOption.CREATE_NEW);
            CSVPrinter printer = new CSVPrinter(writer, plateFileFormat);
        ){
            printer.printComment("Cell source file name: " + sourceFileName);
            printer.printComment("Each row represents one well on the plate.");
            printer.printComment("Plate size: " + size);
            printer.printComment("Error rate: " + error);
            printer.printComment("Concentrations: " + concenString);
            if(isExponential){
                printer.printComment("Lambda: " + lambda);
            }
            else {
                printer.printComment("Std. dev.: " + stdDev);
            }
            printer.printRecords(wellsAsStrings);
        } catch(IOException ex){
            System.out.println("Could not make new file named "+filename);
            System.err.println(ex);
        }
    }
}
