package at.acdp.urweb.web;
import at.acdp.urweb.Main;
import at.acdp.urweb.fhpp.Status;
import com.nmote.xr.XRMethod;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.ExecutionException;

public class FestoXRServer {
    private final static Logger logger = LoggerFactory.getLogger(FestoXRServer.class);

    @XRMethod(value = "example.helloWorld", help = "Returns 'Helo ' + argument")
    public static String hello(Object s) {
        return "Hello '" + s + "'";
    }

    @XRMethod(value = "ref2", help = "ref")
    public static String ref(String a, String b) {
        return "ref";
    }

    @XRMethod(value = "rel", help = "rel")
    public static String rel(int relPos, int speed) {
        try {
            logger.info("rel  {}", relPos);
            int curPos=Main.fhm.readStatus().get().istPosition;
            int targetPos=curPos+relPos;
            logger.info("Relative by {} from {} to {} speed {}", relPos, curPos, targetPos, speed);
            Main.fhm.bereitschaft();
            if(!Main.fhm.readStatus().get().enabled) {
                logger.info("Controller not enabled");
                return "Controller not enabled";
            }
            Main.fhm.direktAuftrag(relPos, speed,0, true);
            Thread.sleep(10);
            Main.fhm.direktAuftrag(relPos, speed, 1, true);
            Thread.sleep(10);

            while(true) {
                boolean reached=checkPos(targetPos);
                if(reached) {
                    logger.info("Reached {}", targetPos);
                    return "OK";
                }
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        } catch (ExecutionException|InterruptedException e) {
            logger.warn("abs failed", e);
            return "abs failed: "+e.toString() ;
        }
    }

    @XRMethod(value = "abs", help = "abs")
    public static String abs(int targetPos, int speed) {
        try {
            logger.info("Absolute to {} speed {}", targetPos, speed);
            Main.fhm.bereitschaft();
            if(!Main.fhm.readStatus().get().enabled) {
                logger.info("Controller not enabled");
                return "Controller not enabled";
           }
        Main.fhm.direktAuftrag(targetPos, speed, 0, false);
        Thread.sleep(100);
        Main.fhm.direktAuftrag(targetPos, speed, 1, false);

        while(true) {
            boolean reached=checkPos(targetPos);
            if(reached) {
                logger.info("Reached {}", targetPos);
                return "OK";
            }
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        } catch (ExecutionException|InterruptedException e) {
            logger.warn("abs failed", e);
            return "abs failed: "+e.toString();
        }
    }

    @XRMethod(value = "getpos", help = "getpos")
    public static int getpos() {
        logger.info("GetPos");
        try {
            return Main.fhm.readStatus().get().istPosition;
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        return -1;
    }

    @XRMethod(value = "ready", help = "ready")
    public static void ready() {
        logger.info("Ready Begin");
        Main.fhm.bereitschaft();
        logger.info("Ready End");
    }

    private static boolean checkPos(int pos) {
            try {
                Status s= Main.fhm.readStatus().get();
                int curPos = s.istPosition;

                logger.info("curpos {} ({})", curPos, pos);
                if(curPos==pos) {
                    logger.info("reached {}", pos);
                    return true;
                }
                if(s.istMoment==0 && Math.abs(curPos-pos) <5) {
                    logger.info("reached {} (moment=0)", pos);
                    return true;
                }
                Thread.sleep(500);
            } catch (ExecutionException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        return false;
    }



    @XRMethod(value = "status", help = "Returns status")
    public static String status() {
        var x=Main.fhm.readStatus();
        try {
            return x==null?"<null>":x.get().toString();
        } catch (Exception e) {
            e.printStackTrace();
            return e.toString();
        }
    }
}
