package party.bami.eqfix.preset;

import android.content.Context;

import java.io.*;
import java.util.Arrays;

import android.util.Log;
import party.bami.eqfix.analysis.PresetEmptyException;
import party.bami.eqfix.analysis.PresetInvalidFileException;
import party.bami.eqfix.other.ParseDirectories;

enum PresetState {
    EMPTY,
    SET
}

public class EQFPreset {
    private PresetState state;
    private Context context;
    private float[] kernel;
    private float delayL;
    private float delayR;
    private float bass;
    private float mid;
    private float treble;

    public EQFPreset(Context context) {
        this.state = PresetState.EMPTY;
        this.context = context;
    }

    public EQFPreset(float[] kernel, float delayL, float delayR) {
        this.state = PresetState.SET;
        this.kernel = kernel;
        this.delayL = delayL;
        this.delayR = delayR;
        this.bass = 0.0f;
        this.mid = 0.0f;
        this.treble = 0.0f;
    }

    /**
     * Loads preset data from a given file and stores the parameters in this EQFPreset object.
     * @param fP A string containing the path of the file which as to be loaded.
     * @throws PresetInvalidFileException
     * @throws FileNotFoundException
     * @throws IOException
     */
    public void load(String fP) throws PresetInvalidFileException, FileNotFoundException, IOException {
        this.state = PresetState.SET;
        InputStream inputStream = context.openFileInput(party.bami.eqfix.other.ParseDirectories.getFilePreset(fP));
        InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
//        BufferedReader br = new BufferedReader(new FileReader(fP));
        BufferedReader br = new BufferedReader(inputStreamReader);
        // Ignore first two lines
        br.readLine();
        br.readLine();
        // Read filter kernel parameters
        String kernelLine = br.readLine();
        // Ignore 4th line
        br.readLine();
        // Read delay for left and right channel
        String delayLine = br.readLine();
        // Ignore 6th line
        br.readLine();
        // Read user parameters
        String paramLine = br.readLine();

        this.kernel = strToFloat(kernelLine.split(" "));
        float[] delays = strToFloat(delayLine.split(" "));
        this.delayL = delays[0];
        this.delayR = delays[1];
        float[] params = strToFloat(paramLine.split(" "));
        this.bass = params[0];
        this.mid = params[1];
        this.treble = params[2];
    }

    /**
     *
     * @param fP A string containing the path of the file which as to be loaded.
     * @throws PresetEmptyException
     * @throws IOException
     */
    public void save(String fP) throws PresetEmptyException, IOException {
        if (this.state == PresetState.EMPTY) {
            throw new PresetEmptyException("Can't save empty presets");
        }
        FileWriter fW = new FileWriter(ParseDirectories.getSavePath() +  "/" +  fP);

        System.out.println(ParseDirectories.getSavePath());


        String contents = "-------EQFix preset file-------\n";
        contents += "--Filter kernel--\n";


        for (int i = 0; i < this.kernel.length; i++) {
            contents += this.kernel[i];

            if (i == (this.kernel.length - 1)) {
                contents += "\n";
            } else {
                contents += " ";
            }
        }

        Log.d("DebugMyApp", "save:1 ");


        contents += "--Channel delay--\n";
        contents += this.delayL + " " + this.delayR;

        contents += "--User Parameters--";
        contents += this.bass + " " + this.mid + " " + this.treble;

        Log.d("DebugMyApp", "save:12 ");
//        try {
//
//            OutputStreamWriter outputStreamWriter = new OutputStreamWriter(new FileOutputStream(new File(ParseDirectories.getSavePath() + fP).getAbsolutePath()));
//
//            outputStreamWriter.write(contents);
//            outputStreamWriter.close();
//            Log.d("DebugMyApp", "save SUCCESS:1 ");
//        }
//        catch (IOException e) {
//            System.out.println("File write failed: " + e.toString());
//        }

        Log.d("DebugMyApp", "save:DONE ");
        fW.write(contents);
        fW.close();
    }

    /**
     * Converts a String array to a float array.
     * @param str The string array
     * @return The converted float array
     */
    private float[] strToFloat(String[] str) {
        float[] flt = new float[str.length];

        for (int i = 0; i < str.length; i++) {
            flt[i] = Float.parseFloat(str[i]);
        }

        return flt;
    }

    /**
     * Replaces the current objects parameters with given new ones.
     * @param kernel New kernel
     * @param delayL New left channel delay.
     * @param delayR New right channel delay.
     */
    public void setData(float[] kernel, float delayL, float delayR) {
        this.state = PresetState.SET;
        this.kernel = kernel;
        this.delayL = delayL;
        this.delayR = delayR;
    }

    public void setParams(float bass, float mid, float treble) {
        this.bass = bass;
        this.mid = mid;
        this.treble = treble;
    }

    /**
     * Returns the current preset state.
     * @return the current preset state.
     */
    public PresetState getState() {
        return this.state;
    }

    /**
     * Returns the current kernel.
     * @return The current kernel.
     * @throws PresetEmptyException
     */
    public float[] getKernel() throws PresetEmptyException {
        if (this.state == PresetState.EMPTY) {
            throw new PresetEmptyException("Can't get data from empty presets");
        }
        return this.kernel;
    }

    /**
     * Returns an array containing the current left and right delay.
     * @return An array containing the current left and right delay.
     */
    public float[] getDelay() {
        return new float[]{this.delayL, this.delayR};
    }

    /**
     * Returns the user parameters present in the preset.
     * @return The user parameters present in the preset.
     */
    public float[] getParams() {
        return new float[]{this.bass, this.mid, this.treble};
    }
}
