package unusedcodes;

import Camera.ArducamIMX477Preset;
import Config.CameraConfig;
import Config.CameraConfigEnum;
import lombok.Getter;
import lombok.val;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.file.Path;
import java.util.Properties;

import static Config.SomeCodes.*;

@SuppressWarnings("unused")
@Getter
public class ConfigFile_Arducam {
    private  String AudioPhase1;
    private String AudioPhase2;
    private String AudioPhase3;
    private String AudioPhase4;
    private String AudioPhase5;

    private String CameraLeft90;
    private String CameraLeft45;
    private String CameraCenter;
    private String CameraRight45;
    private String CameraRight90;

    private CameraConfig ConfigLeft90 = new CameraConfig();
    private CameraConfig ConfigLeft45 = new CameraConfig();
    private CameraConfig ConfigCenter = new CameraConfig();
    private CameraConfig ConfigRight45 =new CameraConfig();
    private CameraConfig ConfigRight90 = new CameraConfig();

    private String FTPHost;
    private String FTPPort;
    private String FTPUser;
    private String FTPPass;
    private String FTPPath;

    private String PhotoDirectory;

    private boolean needsave = false;

    public ConfigFile_Arducam(){

        System.out.println("Current working directory in Java : " + currentDirectory);
        Load();
    }

    public void SetPhotoDirectory(String path){
        if (ValidString(path)){
            if (!path.equals(PhotoDirectory)){
                File ff = new File(path);
                if (ff.isDirectory()){
                    PhotoDirectory = path;
                    needsave = true;
                }
            }
        }
    }

    public void SetAudioPhase1(String path){
        if (ValidString(path)){
            if (!path.equals(AudioPhase1)){
                AudioPhase1 = path;
                needsave = true;
            }
        }
    }

    public void SetAudioPhase2(String path){
        if (ValidString(path)){
            if (!path.equals(AudioPhase2)){
                AudioPhase2 = path;
                needsave = true;
            }
        }
    }

    public void SetAudioPhase3(String path){
        if (ValidString(path)){
            if (!path.equals(AudioPhase3)){
                AudioPhase3 = path;
                needsave = true;
            }
        }
    }

    public void SetAudioPhase4(String path){
        if (ValidString(path)){
            if (!path.equals(AudioPhase4)){
                AudioPhase4 = path;
                needsave = true;
            }
        }
    }

    public void SetAudioPhase5(String path){
        if (ValidString(path)){
            if (!path.equals(AudioPhase5)){
                AudioPhase5 = path;
                needsave = true;
            }
        }
    }

    /**
     * Set Camera Path for Left 90 Degree
     * @param path Path to Camera, or empty string to disable
     */
    public void SetCameraLeft90(String path){
        if (path==null) path="";
        if (!path.equals(CameraLeft90)){
            CameraLeft90 = path;
            needsave = true;
        }
    }

    /**
     * Set Camera Path for Left 45 Degree
     * @param path Path to Camera, or empty string to disable
     */
    public void SetCameraLeft45(String path){
        if (path==null) path="";
        if (!path.equals(CameraLeft45)){
            CameraLeft45 = path;
            needsave = true;
        }
    }

    /**
     * Set Camera Path for Center
     * @param path Path to Camera, or empty string to disable
     */
    public void SetCameraCenter(String path){
        if (path==null) path="";
        if (!path.equals(CameraCenter)){
            CameraCenter = path;
            needsave = true;
        }
    }

    /**
     * Set Camera Path for Right 45 Degree
     * @param path Path to Camera, or empty string to disable
     */
    public void SetCameraRight45(String path){
        if (path==null) path="";
        if (!path.equals(CameraRight45)){
            CameraRight45 = path;
            needsave = true;
        }
    }

    /**
     * Set Camera Path for Right 90 Degree
     * @param path Path to Camera, or empty string to disable
     */
    public void SetCameraRight90(String path){
        if (path==null) path="";
        if (!path.equals(CameraRight90)){
            CameraRight90 = path;
            needsave = true;
        }
    }

    public void SetFTPHost(String host){
        if (ValidString(host)){
            if (!host.equals(FTPHost)){
                FTPHost = host;
                needsave = true;

            }
        }
    }

    public void SetFTPPort(String port){
        if (ValidString(port)){
            if (!port.equals(FTPPort)){
                if (ValidPortNumber(toInt(port))){
                    FTPPort = port;
                    needsave = true;
                }
            }
        }
    }

    public void SetFTPUser(String user){
        if (ValidString(user)){
            if (!user.equals(FTPUser)){
                FTPUser = user;
                needsave = true;
            }
        }
    }

    public void SetFTPPass(String pass){
        if (ValidString(pass)){
            if (!pass.equals(FTPPass)){
                FTPPass = pass;
                needsave = true;
            }
        }
    }

    public void SetFTPPath(String path){
        if (ValidString(path)){
            if (!path.equals(FTPPath)){
                FTPPath = path;
                needsave = true;
            }
        }
    }

    public void setBrightness(CameraConfigEnum cc, double value){
        CameraConfig conf = switch (cc) {
            case CameraConfigLeft90 -> ConfigLeft90;
            case CameraConfigLeft45 -> ConfigLeft45;
            case CameraConfigCenter -> ConfigCenter;
            case CameraConfigRight45 -> ConfigRight45;
            case CameraConfigRight90 -> ConfigRight90;
        };
        if (conf.Brightness != value){
            conf.Brightness = value;
            needsave = true;
        }
    }

    public double getBrightness(CameraConfigEnum cc){
        return switch (cc) {
            case CameraConfigLeft90 -> ConfigLeft90.Brightness;
            case CameraConfigLeft45 -> ConfigLeft45.Brightness;
            case CameraConfigCenter -> ConfigCenter.Brightness;
            case CameraConfigRight45 -> ConfigRight45.Brightness;
            case CameraConfigRight90 -> ConfigRight90.Brightness;
        };
    }

    public void setContrast(CameraConfigEnum cc, double value){
        CameraConfig conf = switch (cc) {
            case CameraConfigLeft90 -> ConfigLeft90;
            case CameraConfigLeft45 -> ConfigLeft45;
            case CameraConfigCenter -> ConfigCenter;
            case CameraConfigRight45 -> ConfigRight45;
            case CameraConfigRight90 -> ConfigRight90;
        };
        if (conf.Contrast != value){
            conf.Contrast = value;
            needsave = true;
        }
    }

    public double getContrast(CameraConfigEnum cc){
        return switch (cc){
            case CameraConfigLeft90 -> ConfigLeft90.Contrast;
            case CameraConfigLeft45 -> ConfigLeft45.Contrast;
            case CameraConfigCenter -> ConfigCenter.Contrast;
            case CameraConfigRight45 -> ConfigRight45.Contrast;
            case CameraConfigRight90 -> ConfigRight90.Contrast;
        };
    }

    public void setSaturation(CameraConfigEnum cc, double value){
        CameraConfig conf = switch (cc) {
            case CameraConfigLeft90 -> ConfigLeft90;
            case CameraConfigLeft45 -> ConfigLeft45;
            case CameraConfigCenter -> ConfigCenter;
            case CameraConfigRight45 -> ConfigRight45;
            case CameraConfigRight90 -> ConfigRight90;
        };
        if (conf.Saturation != value){
            conf.Saturation = value;
            needsave = true;
        }
    }

    public double getSaturation(CameraConfigEnum cc){
        return switch (cc){
            case CameraConfigLeft90 -> ConfigLeft90.Saturation;
            case CameraConfigLeft45 -> ConfigLeft45.Saturation;
            case CameraConfigCenter -> ConfigCenter.Saturation;
            case CameraConfigRight45 -> ConfigRight45.Saturation;
            case CameraConfigRight90 -> ConfigRight90.Saturation;
        };
    }

    public void setHue(CameraConfigEnum cc, double value){
        CameraConfig conf = switch (cc) {
            case CameraConfigLeft90 -> ConfigLeft90;
            case CameraConfigLeft45 -> ConfigLeft45;
            case CameraConfigCenter -> ConfigCenter;
            case CameraConfigRight45 -> ConfigRight45;
            case CameraConfigRight90 -> ConfigRight90;
        };
        if (conf.Hue != value){
            conf.Hue = value;
            needsave = true;
        }
    }

    public double getHue(CameraConfigEnum cc){
        return switch (cc){
            case CameraConfigLeft90 -> ConfigLeft90.Hue;
            case CameraConfigLeft45 -> ConfigLeft45.Hue;
            case CameraConfigCenter -> ConfigCenter.Hue;
            case CameraConfigRight45 -> ConfigRight45.Hue;
            case CameraConfigRight90 -> ConfigRight90.Hue;
        };
    }

    public void setGain(CameraConfigEnum cc, double value){
        CameraConfig conf = switch (cc) {
            case CameraConfigLeft90 -> ConfigLeft90;
            case CameraConfigLeft45 -> ConfigLeft45;
            case CameraConfigCenter -> ConfigCenter;
            case CameraConfigRight45 -> ConfigRight45;
            case CameraConfigRight90 -> ConfigRight90;
        };
        if (conf.Gain != value){
            conf.Gain = value;
            needsave = true;
        }
    }

    public double getGain(CameraConfigEnum cc){
        return switch (cc){
            case CameraConfigLeft90 -> ConfigLeft90.Gain;
            case CameraConfigLeft45 -> ConfigLeft45.Gain;
            case CameraConfigCenter -> ConfigCenter.Gain;
            case CameraConfigRight45 -> ConfigRight45.Gain;
            case CameraConfigRight90 -> ConfigRight90.Gain;
        };
    }

    public void setExposure(CameraConfigEnum cc, double value){
        CameraConfig conf = switch (cc) {
            case CameraConfigLeft90 -> ConfigLeft90;
            case CameraConfigLeft45 -> ConfigLeft45;
            case CameraConfigCenter -> ConfigCenter;
            case CameraConfigRight45 -> ConfigRight45;
            case CameraConfigRight90 -> ConfigRight90;
        };
        if (conf.Exposure != value){
            conf.Exposure = value;
            needsave = true;
        }
    }

    public double getExposure(CameraConfigEnum cc){
        return switch (cc){
            case CameraConfigLeft90 -> ConfigLeft90.Exposure;
            case CameraConfigLeft45 -> ConfigLeft45.Exposure;
            case CameraConfigCenter -> ConfigCenter.Exposure;
            case CameraConfigRight45 -> ConfigRight45.Exposure;
            case CameraConfigRight90 -> ConfigRight90.Exposure;
        };
    }

    public void setSharpness(CameraConfigEnum cc, double value){
        CameraConfig conf = switch (cc) {
            case CameraConfigLeft90 -> ConfigLeft90;
            case CameraConfigLeft45 -> ConfigLeft45;
            case CameraConfigCenter -> ConfigCenter;
            case CameraConfigRight45 -> ConfigRight45;
            case CameraConfigRight90 -> ConfigRight90;
        };
        if (conf.Sharpness != value){
            conf.Sharpness = value;
            needsave = true;
        }
    }

    public double getSharpness(CameraConfigEnum cc){
        return switch (cc){
            case CameraConfigLeft90 -> ConfigLeft90.Sharpness;
            case CameraConfigLeft45 -> ConfigLeft45.Sharpness;
            case CameraConfigCenter -> ConfigCenter.Sharpness;
            case CameraConfigRight45 -> ConfigRight45.Sharpness;
            case CameraConfigRight90 -> ConfigRight90.Sharpness;
        };
    }

    public void setGamma(CameraConfigEnum cc, double value){
        CameraConfig conf = switch (cc) {
            case CameraConfigLeft90 -> ConfigLeft90;
            case CameraConfigLeft45 -> ConfigLeft45;
            case CameraConfigCenter -> ConfigCenter;
            case CameraConfigRight45 -> ConfigRight45;
            case CameraConfigRight90 -> ConfigRight90;
        };
        if (conf.Gamma != value){
            conf.Gamma = value;
            needsave = true;
        }
    }

    public double getGamma(CameraConfigEnum cc){
        return switch (cc){
            case CameraConfigLeft90 -> ConfigLeft90.Gamma;
            case CameraConfigLeft45 -> ConfigLeft45.Gamma;
            case CameraConfigCenter -> ConfigCenter.Gamma;
            case CameraConfigRight45 -> ConfigRight45.Gamma;
            case CameraConfigRight90 -> ConfigRight90.Gamma;
        };
    }

    public void setAutoExposure(CameraConfigEnum cc, boolean value){
        CameraConfig conf = switch (cc) {
            case CameraConfigLeft90 -> ConfigLeft90;
            case CameraConfigLeft45 -> ConfigLeft45;
            case CameraConfigCenter -> ConfigCenter;
            case CameraConfigRight45 -> ConfigRight45;
            case CameraConfigRight90 -> ConfigRight90;
        };
        if (conf.AutoExposure != value){
            conf.AutoExposure = value;
            needsave = true;
        }
    }

    public boolean getAutoExposure(CameraConfigEnum cc){
        return switch (cc){
            case CameraConfigLeft90 -> ConfigLeft90.AutoExposure;
            case CameraConfigLeft45 -> ConfigLeft45.AutoExposure;
            case CameraConfigCenter -> ConfigCenter.AutoExposure;
            case CameraConfigRight45 -> ConfigRight45.AutoExposure;
            case CameraConfigRight90 -> ConfigRight90.AutoExposure;
        };
    }

    public void setAutoFocus(CameraConfigEnum cc, boolean value){
        CameraConfig conf = switch (cc) {
            case CameraConfigLeft90 -> ConfigLeft90;
            case CameraConfigLeft45 -> ConfigLeft45;
            case CameraConfigCenter -> ConfigCenter;
            case CameraConfigRight45 -> ConfigRight45;
            case CameraConfigRight90 -> ConfigRight90;
        };
        if (conf.AutoFocus != value){
            conf.AutoFocus = value;
            needsave = true;
        }
    }

    public boolean getAutoFocus(CameraConfigEnum cc){
        return switch (cc){
            case CameraConfigLeft90 -> ConfigLeft90.AutoFocus;
            case CameraConfigLeft45 -> ConfigLeft45.AutoFocus;
            case CameraConfigCenter -> ConfigCenter.AutoFocus;
            case CameraConfigRight45 -> ConfigRight45.AutoFocus;
            case CameraConfigRight90 -> ConfigRight90.AutoFocus;
        };
    }

    public void setAutoWhiteBalance(CameraConfigEnum cc, boolean value){
        CameraConfig conf = switch (cc) {
            case CameraConfigLeft90 -> ConfigLeft90;
            case CameraConfigLeft45 -> ConfigLeft45;
            case CameraConfigCenter -> ConfigCenter;
            case CameraConfigRight45 -> ConfigRight45;
            case CameraConfigRight90 -> ConfigRight90;
        };
        if (conf.AutoWhiteBalance != value){
            conf.AutoWhiteBalance = value;
            needsave = true;
        }
    }

    public boolean getAutoWhiteBalance(CameraConfigEnum cc){
        return switch (cc){
            case CameraConfigLeft90 -> ConfigLeft90.AutoWhiteBalance;
            case CameraConfigLeft45 -> ConfigLeft45.AutoWhiteBalance;
            case CameraConfigCenter -> ConfigCenter.AutoWhiteBalance;
            case CameraConfigRight45 -> ConfigRight45.AutoWhiteBalance;
            case CameraConfigRight90 -> ConfigRight90.AutoWhiteBalance;
        };
    }



    private void Load(){
        File ff = Path.of(currentDirectory, "config.properties").toFile();
        if (ff.isFile()){
            System.out.println("Load config file at "+ff.getPath());
            try{
                Properties prop = new Properties();
                val FIS = new FileInputStream(ff.getPath());
                prop.load(FIS);
                boolean allcorrect = true;
                if (prop.getProperty("AudioPhase1") == null) allcorrect = false;
                if (prop.getProperty("AudioPhase2") == null) allcorrect = false;
                if (prop.getProperty("AudioPhase3") == null) allcorrect = false;
                if (prop.getProperty("AudioPhase4") == null) allcorrect = false;
                if (prop.getProperty("AudioPhase5") == null) allcorrect = false;
                if (prop.getProperty("CameraLeft90") == null) allcorrect = false;
                if (prop.getProperty("CameraLeft45") == null) allcorrect = false;
                if (prop.getProperty("CameraCenter") == null) allcorrect = false;
                if (prop.getProperty("CameraRight45") == null) allcorrect = false;
                if (prop.getProperty("CameraRight90") == null) allcorrect = false;
                if (prop.getProperty("FTPHost") == null) allcorrect = false;
                if (prop.getProperty("FTPPort") == null) allcorrect = false;
                if (prop.getProperty("FTPUser") == null) allcorrect = false;
                if (prop.getProperty("FTPPass") == null) allcorrect = false;
                if (prop.getProperty("FTPPath") == null) allcorrect = false;
                if (prop.getProperty("PhotoDirectory") == null) allcorrect = false;

                if (prop.getProperty(CameraConfigEnum.CameraConfigLeft90.toString()) == null) allcorrect = false;
                if (prop.getProperty(CameraConfigEnum.CameraConfigLeft45.toString()) == null) allcorrect = false;
                if (prop.getProperty(CameraConfigEnum.CameraConfigCenter.toString()) == null) allcorrect = false;
                if (prop.getProperty(CameraConfigEnum.CameraConfigRight45.toString()) == null) allcorrect = false;
                if (prop.getProperty(CameraConfigEnum.CameraConfigRight90.toString()) == null) allcorrect = false;

                if (allcorrect){
                    AudioPhase1 = prop.getProperty("AudioPhase1");
                    AudioPhase2 = prop.getProperty("AudioPhase2");
                    AudioPhase3 = prop.getProperty("AudioPhase3");
                    AudioPhase4 = prop.getProperty("AudioPhase4");
                    AudioPhase5 = prop.getProperty("AudioPhase5");

                    CameraLeft90 = prop.getProperty("CameraLeft90");
                    CameraLeft45 = prop.getProperty("CameraLeft45");
                    CameraCenter = prop.getProperty("CameraCenter");
                    CameraRight45 = prop.getProperty("CameraRight45");
                    CameraRight90 = prop.getProperty("CameraRight90");

                    FTPHost = prop.getProperty("FTPHost");
                    FTPPort = prop.getProperty("FTPPort");
                    FTPUser = prop.getProperty("FTPUser");
                    FTPPass = prop.getProperty("FTPPass");
                    FTPPath = prop.getProperty("FTPPath");
                    PhotoDirectory = prop.getProperty("PhotoDirectory");

                    ConfigLeft90 = gson.fromJson(prop.getProperty(CameraConfigEnum.CameraConfigLeft90.toString()), CameraConfig.class);
                    ConfigLeft45 = gson.fromJson(prop.getProperty(CameraConfigEnum.CameraConfigLeft45.toString()), CameraConfig.class);
                    ConfigCenter = gson.fromJson(prop.getProperty(CameraConfigEnum.CameraConfigCenter.toString()), CameraConfig.class);
                    ConfigRight45 = gson.fromJson(prop.getProperty(CameraConfigEnum.CameraConfigRight45.toString()), CameraConfig.class);
                    ConfigRight90 = gson.fromJson(prop.getProperty(CameraConfigEnum.CameraConfigRight90.toString()), CameraConfig.class);

                    System.out.println("Config Loaded");
                    return;
                } else System.out.println("Config File Not Correct, Creating Default");
            } catch (Exception e){
                System.out.println("Error Load Config: " + e.getMessage()+", Creating Default");
            }
        } else System.out.println("Config File Not Found, Creating Default");
        CreateDefault();
    }

    private void CreateDefault(){
        AudioPhase1 = Path.of(currentDirectory, "audio", "phase1.mp3").toString();
        AudioPhase2 = Path.of(currentDirectory, "audio", "phase2.mp3").toString();
        AudioPhase3 = Path.of(currentDirectory, "audio", "phase3.mp3").toString();
        AudioPhase4 = Path.of(currentDirectory, "audio", "phase4.mp3").toString();
        AudioPhase5 = Path.of(currentDirectory, "audio", "phase5.mp3").toString();
        CameraLeft90 = "";
        CameraLeft45 = "";
        CameraCenter = "";
        CameraRight45 = "";
        CameraRight90 = "";
        FTPHost = "192.168.10.2";
        FTPPort = "21";
        FTPUser = "user";
        FTPPass = "password";
        FTPPath = "/";
        PhotoDirectory = currentDirectory;
        SetDefaultCameraConfig(ConfigLeft90);
        SetDefaultCameraConfig(ConfigLeft45);
        SetDefaultCameraConfig(ConfigCenter);
        SetDefaultCameraConfig(ConfigRight45);
        SetDefaultCameraConfig(ConfigRight90);
        System.out.println("Default Config Created");
        needsave = true;
        Save();
    }

    private void SetDefaultCameraConfig(CameraConfig cc){
        if (cc!=null){
            cc.AutoExposure = true;
            cc.AutoFocus = true;
            cc.AutoWhiteBalance = true;
            cc.Brightness = ArducamIMX477Preset.Brightness.Default;
            cc.Contrast = ArducamIMX477Preset.Contrast.Default;
            cc.Exposure = ArducamIMX477Preset.ExposureTime.Default;
            cc.Gain = ArducamIMX477Preset.Gain.Default;
            cc.Saturation = ArducamIMX477Preset.Saturation.Default;
            cc.Hue = ArducamIMX477Preset.Hue.Default;
            cc.Gamma = ArducamIMX477Preset.Gamma.Default;
            cc.Sharpness = ArducamIMX477Preset.Sharpness.Default;
        }
    }

    public void Save(){
        if (!needsave) return;
        needsave = false;
        Properties prop = new Properties();
        prop.setProperty("AudioPhase1", AudioPhase1);
        prop.setProperty("AudioPhase2", AudioPhase2);
        prop.setProperty("AudioPhase3", AudioPhase3);
        prop.setProperty("AudioPhase4", AudioPhase4);
        prop.setProperty("AudioPhase5", AudioPhase5);

        prop.setProperty("CameraLeft90", CameraLeft90);
        prop.setProperty("CameraLeft45", CameraLeft45);
        prop.setProperty("CameraCenter", CameraCenter);
        prop.setProperty("CameraRight45", CameraRight45);
        prop.setProperty("CameraRight90", CameraRight90);

        prop.setProperty("FTPHost", FTPHost);
        prop.setProperty("FTPPort", FTPPort);
        prop.setProperty("FTPUser",FTPUser);
        prop.setProperty("FTPPass", FTPPass);
        prop.setProperty("FTPPath", FTPPath);
        prop.setProperty("PhotoDirectory", PhotoDirectory);

        prop.setProperty(CameraConfigEnum.CameraConfigLeft90.toString(), gson.toJson(ConfigLeft90));
        prop.setProperty(CameraConfigEnum.CameraConfigLeft45.toString(), gson.toJson(ConfigLeft45));
        prop.setProperty(CameraConfigEnum.CameraConfigCenter.toString(), gson.toJson(ConfigCenter));
        prop.setProperty(CameraConfigEnum.CameraConfigRight45.toString(), gson.toJson(ConfigRight45));
        prop.setProperty(CameraConfigEnum.CameraConfigRight90.toString(), gson.toJson(ConfigRight90));

        try{
            prop.store(new FileOutputStream(Path.of(currentDirectory, "config.properties").toString()), null);
            System.out.println("Config Saved");
        } catch (Exception e){
            System.out.println("Error Save Config: " + e.getMessage());
        }
    }
}
