'use strict';

// To de done:
//  - CheckLID status (should be open or closed)
//  - Is it necessary to switch the bias-voltage off?
//  - Get reasonable timeouts for all steps (wait, get, run)
//  - Improve order to accelerate execution
//
// =================================================================

/*
var table =
[
 [ "AGILENT_CONTROL" ],
 [ "BIAS_CONTROL"    ],
 [ "CHAT"            ],
 [ "DATA_LOGGER"     ],
 [ "DRIVE_CONTROL"   ],
 [ "FEEDBACK"        ],
 [ "FAD_CONTROL"     ],
 [ "FSC_CONTROL"     ],
 [ "FTM_CONTROL"     ],
 [ "LID_CONTROL"     ],
 [ "MAGIC_WEATHER"   ],
 [ "MCP"             ],
 [ "PWR_CONTROL"     ],
 [ "RATE_CONTROL"    ],
 [ "RATE_SCAN"       ],
 [ "SMART_FACT"      ],
 [ "TIME_CHECK"      ],
 [ "TNG_WEATHER"     ],
];

if (dim.state("DRIVE_CONTROL").name=="Locked")
{
    throw new Error("Drivectrl still locked... needs UNLOCK first.");
    //while (!dim.send("DRIVE_CONTROL"))
    //    v8.sleep();
    //dim.send("DRIVE_CONTROL/UNLOCK");
    //dim.wait("DRIVE_CONTROL", "Armed", 1000);
}

*/

console.out("");

var loop;
include("scripts/Handler.js");
include("scripts/CheckStates.js");

// -----------------------------------------------------------------
// Make sure camera electronics is switched on and has power
// -----------------------------------------------------------------

include("scripts/handleAgilentPowerOn.js");
include("scripts/handlePwrCameraOn.js");

checkSend(["AGILENT_CONTROL","PWR_CONTROL"]);

loop = new Handler("PowerOn");
loop.add(handleAgilentPowerOn);
loop.add(handlePwrCameraOn);
loop.run();
console.out("");

// If power was switched on: wait for a few seconds

// -----------------------------------------------------------------
// Now take care that the bias control, the ftm and the fsc are
// properly connected and are in a reasonable state (e.g. the
// trigger is switched off)
// -----------------------------------------------------------------

include("scripts/handleBiasVoltageOff.js");
include("scripts/handleFtmIdle.js");
include("scripts/handleFscConnected.js");
include("scripts/handleFeedbackConnected.js");
include("scripts/handleRatectrlConnected.js");
include("scripts/handleLidClosed.js");

checkSend(["BIAS_CONTROL","FTM_CONTROL", "FSC_CONTROL", "FEEDBACK", "RATE_CONTROL"]);

// Missing MCP --> Idle
loop = new Handler("SystemSetup");
loop.add(handleBiasVoltageOff);
loop.add(handleFtmIdle);
loop.add(handleFscConnected);
loop.add(handleFeedbackConnected); // Feedback needs FAD to be Connected
loop.add(handleRatectrlConnected);
//loop.add(handleLidClosed);
loop.run();

console.out("Bias crate connected and voltage off.");
console.out("Feedback switched off.");
console.out("FTM connected and idle.");
console.out("FSC connected.");
console.out("Rate control connected.");
//console.out("Lids closed.");
console.out("");

console.out("Enable all FTU");
dim.send("FTM_CONTROL/ENABLE_FTU", -1, true);

// -----------------------------------------------------------------
// Now we check the FTU connection
// -----------------------------------------------------------------

/*
include("scripts/handleFtuCheck.js");

loop = new Handler("FtuCheck");
loop.ftuList = new Subscription("FTM_CONTROL/FTU_LIST");
loop.add(handleFtuCheck);
loop.run();
loop.ftuList.close();

dim.log("All FTUs are enabled and without error.");
*/

console.out("Checking FTU: start");
include("scripts/CheckFTU.js");
console.out("Checking FTU: done");
console.out("");

// -----------------------------------------------------------------
// Now we can safely try to connect the FAD boards.
// -----------------------------------------------------------------

// If FADs already connected
include("scripts/handleFadConnected.js");

checkSend(["FAD_CONTROL"]);

loop = new Handler("ConnectFad");
loop.add(handleFadConnected);
loop.run();

var failed = false;
dim.onchange["FAD_CONTROL"] = function(arg)
{
    if (this.rc && arg.name!="Connected")
        failed = true;
}

console.out("FADs connected.");
console.out("");

console.out(dim.state("FAD_CONTROL").name);
console.out(dim.state("MCP").name);

// ================================================================
// Underflow check
// ================================================================
// Is it necessary to check for the so called 'underflow-problem'?
// (This is necessary after each power cycle)
// ----------------------------------------------------------------

include('scripts/CheckUnderflow.js');

// Now it is time to check the connection of the FADs
// it might hav thrown an exception already anyway


// ================================================================
// Power on drive system if power is off (do it hre to make sure not
// everything is switchd on at the same time)
// ================================================================

console.out("PWR: "+(dim.state("PWR_CONTROL").index&16));

if ((dim.state("PWR_CONTROL").index&16)==0)
{
    console.out("Drive on");
    dim.send("PWR_CONTROL/TOGGLE_DRIVE");
}
    include("scripts/handleDriveArmed.js");

    checkSend(["DRIVE_CONTROL"]);

    loop = new Handler("ArmDrive");
    loop.add(handleDriveArmed);
    loop.run();


// ================================================================
// Bias crate calibration
// ================================================================
// Bias crate calibration if necessary (it is aftr 4pm (local tome)
// and the last calibration was more than eight hours ago.
// -----------------------------------------------------------------

// At this point we know that:
//  1) The lid is closed
//  2) The feedback is stopped
//  3) The voltage is off

// Check age of calibration
var service_calibration = new Subscription("FEEDBACK/CALIBRATION");

var data_calibration = service_calibration.get(-5000);
//if (!data_calibration)
//    throw new Error("Could not connect to FEEDBACK/CALIBRATION");

function makeCurrentCalibration( reason_string  )
{
     console.out( reason_string );
 
     dim.send("BIAS_CONTROL/SET_GLOBAL_DAC", 1);
     dim.wait("BIAS_CONTROL", "VoltageOn", 3000);
 
     var now = new Date();
     dim.send("FEEDBACK/CALIBRATE_CURRENTS");

     // FIXME: Timeout!
     console.out("Wait for calibration to start");
     dim.wait("FEEDBACK", "Calibrating", 5000);

     console.out("Wait for calibration to end");
     dim.wait("FEEDBACK", "Connected", 60000);

     console.out("Calibration took "+(new Date()-now)+"ms");

     console.out("Wait for voltage to be off");
     dim.send("BIAS_CONTROL/SET_ZERO_VOLTAGE");
     dim.wait("BIAS_CONTROL", "VoltageOff", 5000);
}

if (!data_calibration)
{
   // FEEDBACK might just be freshly started and 
   // will not yet serve this service.
   var reason_msg = "No current calibration avaliable. New calibration needed.";
   makeCurrentCalibration( reason_msg );
}
else 
{
    var age = data_calibration.time;
    var now = new Date();

    //service_calibration.close();

    var diff = (now-age)/3600000;

    if ((diff>8 && now.getHours()>16)/* || empty*/)
    {
        var reason_msg = "Last BIAS crate calibration taken at "+age.toUTCString()+": New calibration needed.";
        makeCurrentCalibration( reason_msg );
    }
}




// ================================================================
// Crosscheck all states
// ================================================================

var table =
[
 [ "TNG_WEATHER"   ],
 [ "MAGIC_WEATHER" ],
 [ "CHAT"          ],
 [ "SMART_FACT"    ],
 [ "DATA_LOGGER",     [ "NightlyFileOpen", "WaitForRun"   ] ],
 [ "FSC_CONTROL",     [ "Connected"                       ] ],
 [ "MCP",             [ "Idle"                            ] ],
 [ "TIME_CHECK",      [ "Valid"                           ] ],
 [ "PWR_CONTROL",     [ "SystemOn"                        ] ],
 [ "AGILENT_CONTROL", [ "VoltageOn"                       ] ],
 [ "BIAS_CONTROL",    [ "VoltageOn", "VoltageOff"         ] ],
 [ "FEEDBACK",        [ "Connected"                       ] ],
 [ "RATE_SCAN",       [ "Connected"                       ] ],
 [ "RATE_CONTROL",    [ "Connected"                       ] ],
 [ "LID_CONTROL",     [ "Open", "Closed"                  ] ],
 [ "DRIVE_CONTROL",   [ "Armed", "Tracking", "OnTrack"    ] ],
 [ "FTM_CONTROL",     [ "Idle", "TriggerOn"               ] ],
 [ "FAD_CONTROL",     [ "Connected", "WritingData"        ] ],
];

if (!checkStates(table))
{
    throw new Error("Something unexpected has happened. Although the startup-"+
                    "procedure has finished, not all servers are in the state"+
                    "in which they ought to be. Please, try to find out what"+
                    "happened...");
}


