package wash.control;

import actor.ActorThread;
import wash.control.WashingMessage.Order;
import wash.io.WashingIO;
import wash.io.WashingIO.Spin;

public final class ControllerSpin extends ActorThread<WashingMessage> {
    private WashingIO io;
    private WashingMessage m;
    private WashingMessage temp;
    private boolean ackSent = true;
    private Order spinState = Order.SPIN_OFF;
    long start = System.currentTimeMillis();

    public ControllerSpin(WashingIO io) {
        this.io = io;
    }

    protected void sendAck() {
        m.sendAck(this);
        ackSent = true;
    }

    @Override
    public void run() {
        long elapsed; // "Virtual" seconds elapsed, used for modulo ops in spin direction
        while (true) {
            try {
                temp = receiveWithTimeout(10000 / Settings.SPEEDUP);
                elapsed = ((System.currentTimeMillis() - start) * (Settings.SPEEDUP) / 1000 * 60);

                // If there is a new message, swap
                if (temp != null) {
                    m = temp;
                    ackSent = false; // We have a new order
                }

                // If this message is not the same as last time
                if (m != null && m.order() != spinState) {
                    spinState = m.order();
                }

                switch (spinState) {
                    case Order.SPIN_OFF -> {
                        io.setSpinMode(Spin.IDLE);
                    }
                    case Order.SPIN_FAST -> {
                        io.setSpinMode(Spin.FAST);
                    }
                    case Order.SPIN_SLOW -> {
                        if (elapsed % 2 == 0)
                            io.setSpinMode(Spin.RIGHT);
                        else
                            io.setSpinMode(Spin.LEFT);
                    }
                    default -> {
                        continue;
                    }
                }

                if (m != null && !ackSent)
                    sendAck();
            } catch (Exception e) {
                System.out.println(e);
            }
        }
    }
}
