package SBC;

import lombok.Getter;
import org.pmw.tinylog.Logger;

import java.nio.file.Files;
import java.nio.file.Path;

import static code.common.*;

@SuppressWarnings({"unused", "UnusedReturnValue"})
@Getter
public class GpioOutput {
    private boolean initialized = false;
    private int gpionumber = 0;
    private Path valuePath;
    private Path directionPath;
    private boolean activeHigh = true;
    /**
     * Create GpioInput object
     * Active High : ON = 1, OFF = 0
     * Active Low : ON = 0, OFF = 1
     * @param gpionumber GPIO number
     * @param activeHigh true if active high, false if active low
     */
    public GpioOutput(int gpionumber,boolean activeHigh){
        if (gpionumber>0){
            if (HaveGPIO()){
                if (WriteFile(gpioExportPath,gpionumber)){
                    valuePath = gpioPath.resolve("gpio"+gpionumber).resolve("value");
                    directionPath = gpioPath.resolve("gpio"+gpionumber).resolve("direction");
                    if (Files.exists(valuePath) && Files.exists(directionPath)){
                        if (WriteFile(directionPath,"out")){
                            this.activeHigh = activeHigh;
                            this.gpionumber = gpionumber;
                            initialized = true;
                            SetValue(false);
                            Logger.info("GPIO Output created: {}",gpionumber);
                        } else Logger.info("Failed to set direction to in: {}",gpionumber);
                    } else Logger.info("Failed to export GPIO: {}",gpionumber);
                } else Logger.info("Failed to write export GPIO: {}",gpionumber);
            } else Logger.info("Dont have GPIO path");
        } else Logger.info("Platform is not Linux");
    }

    /**
     * Set GPIO Value
     * @param isON true to set GPIO ON, false to set GPIO OFF
     * @return true if success
     */
    public boolean SetValue(boolean isON){
        if (initialized){
            return WriteFile(valuePath,activeHigh?isON?"1":"0":isON?"0":"1");
        }
        return false;
    }

    /**
     * Set Blink ON for specific delay
     * Blink ON = OFF -> ON -> OFF
     * @param delay delay in milliseconds
     */
    public void BlinkON(int delay){
        SetValue(false);
        SetValue(true);
        try {
            Thread.sleep(delay);
        } catch (InterruptedException ignored) {
        }
        SetValue(false);
    }

    /**
     * Set Blink OFF for specific delay
     * Blink OFF = ON -> OFF -> ON
     * @param delay delay in milliseconds
     */
    public void BlinkOFF(int delay) {
        SetValue(true);
        SetValue(false);
        try {
            Thread.sleep(delay);
        } catch (InterruptedException ignored) {
        }
        SetValue(true);
    }

    /**
     * Close Gpio Input
     */
    public void Close(){
        if (initialized){
            SetValue(false);
            initialized = false;
            WriteFile(gpioUnexportPath,gpionumber);
        }
    }
}
