package SBC;

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

import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;

import static code.common.*;

@SuppressWarnings("unused")
@Getter
public class GpioInput {
    private boolean initialized = false;
    private int gpionumber = 0;
    private Path valuePath;
    private Path directionPath;
    private final AtomicInteger OnCounter = new AtomicInteger(0);
    @Setter private Consumer<Void> onShortPress;
    @Setter private Consumer<Void> onLongPress;

    // 10 x 10ms timer = 100ms
    private final int shortPressTime = 10;
    // 200 x 10ms timer = 2000ms
    private final int longPressTime = 200;

    private void updateShortPressed(){
        if (onShortPress!=null) onShortPress.accept(null);
    }

    private void updateLongPressed(){
        if (onLongPress!=null) onLongPress.accept(null);
    }

    /**
     * Create GpioInput object
     * Active Low = true : 0 = ON, 1 = OFF
     * Active Low = false : 0 = OFF, 1 = ON
     * @param gpionumber GPIO number
     * @param activeLow Active Low
     */
    public GpioInput(int gpionumber, final boolean activeLow){
        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,"in")){
                            this.gpionumber = gpionumber;
                            initialized = true;
                            new Thread(()->{
                                while(initialized){
                                    try{
                                        Thread.sleep(10);
                                    } catch (Exception ignored) {}
                                    String value = ReadFile(valuePath);
                                    if (Objects.equals(value,activeLow?"0":"1")){
                                        OnCounter.incrementAndGet();
                                    } else {
                                        int vv = OnCounter.getAndSet(0);
                                        if (vv>= shortPressTime){
                                            if (vv < longPressTime){
                                                updateShortPressed();
                                            } else {
                                                updateLongPressed();
                                            }
                                        }
                                        // di bawah shortPressTime, diabaikan
                                    }
                                }
                            }).start();
                            Logger.info("GPIO Input 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");
    }

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