package wash.program;

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

import static wash.control.WashingMessage.Order.*;

/**
 * Program 3 for washing machine. This also serves as an example of how washing
 * programs can be structured.
 * 
 * This short program stops all regulation of temperature and water levels,
 * stops the barrel from spinning, and drains the machine of water.
 * 
 * It can be used after an emergency stop (program 0) or a power failure.
 */
public final class WashingProgram3 extends ActorThread<WashingMessage> {

    private WashingIO io;
    private ActorThread<WashingMessage> temp;
    private ActorThread<WashingMessage> water;
    private ActorThread<WashingMessage> spin;
    
    public WashingProgram3(WashingIO io,
                           ActorThread<WashingMessage> temp,
                           ActorThread<WashingMessage> water,
                           ActorThread<WashingMessage> spin) 
    {
        this.io = io;
        this.temp = temp;
        this.water = water;
        this.spin = spin;
    }
    
    @Override
    public void run() {
        try {
            System.out.println("WashingProgram3 Started...");

            io.lock(true);
            
            // Switch off heating
            temp.send(new WashingMessage(this, TEMP_IDLE));
            receive();

            // Spin off just to be sure
            spin.send(new WashingMessage(this, SPIN_OFF));
            receive();

            // Drain water
            water.send(new WashingMessage(this, WATER_DRAIN));
            receive();

            // Unlock hatch
            io.lock(false);
            
            System.out.println("WashingProgram3 Finished...");
        } catch (InterruptedException e) {
            System.out.println("WashingProgram3 Interrupted...");
            // If we end up here, it means the program was interrupt()'ed:
            // set all controllers to idle

            temp.send(new WashingMessage(this, TEMP_IDLE));
            water.send(new WashingMessage(this, WATER_IDLE));
            spin.send(new WashingMessage(this, SPIN_OFF));
        }
    }
}
