var throttleSpeed = 0;          // The speed of the train
var throttleForward = true;     // The direction of the train
var locoPos = 100;          // The position of the loco
// var locoPos = 700;           // The position of the loco
// var locoPos = 830;           // The position of the loco
// var locoPos = 982;           // The position of the loco
// var locoPos = 765;           // The position of the loco
// var locoPos = 707;               // The position of the loco
var selectDivergedTrack = false;    // Should the train go to crane track instead of harbour track?
var turnoutThrown = true;       // Is the turnout thrown?
var diveringTrackAngle = 0;     // The angle of crane track?
var turnoutPos = 0;             // Where does the diverging track starts?
var carPos = 0;                 // Position of the car
var carIsFilled = false;        // Is the car loaded with coal?

var craneX = 737;               // Crane X position
var craneY = 540;               // Crane Y position
var craneMinAngle = -160;       // Minimum angle of the crane
var craneMaxAngle = 90;         // Maximum angle of the crane
var craneAngle = craneMinAngle; // Current angle of crane
// var craneAngle = 59; // Current angle of crane
var commandedCraneAngle = -1;   // Commanded angle of the crane
//var craneUpDown = -1;         // Current crane arm up/down (up = 100, down = 0)
var craneUpDown = 100;          // Current crane arm up/down (up = 100, down = 0)
var commandedCraneUpDown = 0;   // Commanded crane arm up/down (up = 100, down = 0)
var craneBucketOpenClosed = -1; // Current crane bucket open/closed (open = 0, closed = 100)
var commandedCraneBucketOpenClosed = 0; // Commanded crane arm up/down (open = 0, closed = 100)
var craneBucketFilled = false;  // Is the crane bucket filled?

var sensor1_active = false;
var sensor1_Pos = 30;
var sensor2_active = false;
var sensor2_Pos = 760;
var sensor3_active = false;
var sensor3_Pos = 914;

var locoLength = 450 * 0.3;     // 0.3 is the scale factor
var carLength = 437 * 0.3;      // 0.3 is the scale factor



// set the jmri global variable to null
var jmri = null;
$(document).ready(function() {

    calculateDivergingTrackAngle();

    jmri = $.JMRI({

        open: function() {
            jmri.getMemory("IM_7_1");   // Crane angle left - right, commanded position
            jmri.getMemory("IM_7_2");   // Crane angle left - right, actual position
            jmri.getMemory("IM_7_3");   // Crane bucket up - down, commanded position
            jmri.getMemory("IM_7_4");   // Crane bucket up - down, actual position
            jmri.getMemory("IM_7_5");   // Crane bucket closed - open, commanded position
            jmri.getMemory("IM_7_6");   // Crane bucket closed - open, actual position
            jmri.getTurnout("IT_7_1");  // Turnout
            jmri.getSensor("IS_7_1");   // Sensor at turnout
            jmri.getSensor("IS_7_2");   // Sensor at ship
            jmri.getSensor("IS_7_3");   // Sensor at coal yard

//          console.log("Throttle data: ");
//          console.log("MyLoco throttle");
            throttle = {"name": "MyLoco", "address": 21};
            result = jmri.getThrottle(throttle);
        },


        memory: function(name, value, data) {
            if (name == "IM_7_1") rotateCrane(value);
            if (name == "IM_7_3") liftLowerCrane(value);
            if (name == "IM_7_5") openCloseCraneBucket(value);
        },


        turnout: function(name, value, data) {
            turnoutThrown = (value == 4);

            if (turnoutThrown) {
                turnout_1_1.setAttribute("visibility", "hidden");
                turnout_1_2.setAttribute("visibility", "hidden");
                turnout_2_1.setAttribute("visibility", "visible");
                turnout_2_2.setAttribute("visibility", "visible");
            } else {
                turnout_1_1.setAttribute("visibility", "visible");
                turnout_1_2.setAttribute("visibility", "visible");
                turnout_2_1.setAttribute("visibility", "hidden");
                turnout_2_2.setAttribute("visibility", "hidden");
            }
        },


        throttle: function(throttle, data) {
            if (typeof data.speed !== 'undefined') {
//              console.log("Speed: ", data.speed);
                if (data.speed >= 0) throttleSpeed = data.speed;
                else throttleSpeed = 0;
            }
            if (typeof data.forward !== 'undefined') {
//              console.log("Forward: ", data.forward);
                throttleForward = data.forward;
            }
//          for (var key in data2) {
//              console.log(key);
//          }
        },


        // when the JMRI object receives a power update, call this
        // function, regardless of source of update
        power: function(state) {
            power = state;
//          console.log("Power: "+power);
/*
            switch (power) {
                case jmri.UNKNOWN:
                    $('#powerImg').prop('src', "/images/PowerGrey.png");
                    $('#powerImg').prop('alt', "Unknown");
                    $('#powerImg').prop('title', "Unknown");
                    break;
                case jmri.POWER_ON:
                    $('#powerImg').prop('src', "/images/PowerGreen.png");
                    $('#powerImg').prop('alt', "Powered On");
                    $('#powerImg').prop('title', "Powered On");
                    break;
                case jmri.POWER_OFF:
                    $('#powerImg').prop('src', "/images/PowerRed.png");
                    $('#powerImg').prop('alt', "Powered Off");
                    $('#powerImg').prop('title', "Powered Off");
                    break;
            }
*/
        }
    });
    // trigger the initial connection to the JMRI server; this
    // method call ensures the jmri.open() method is called after
    // a timeout to begin using fall back methods for monitoring
    // items on the JMRI server even if a WebSocket connection
    // cannot be established
    jmri.connect();

    // make it possible to click on the power button to turn track
    // power on or off without using a javascript URI
//  $('#powerImg').click(function(event) {
//      jmri.setPower((power === jmri.POWER_ON) ? jmri.POWER_OFF : jmri.POWER_ON);
//  });
});



function calculateDivergingTrackAngle()
{
    var track = document.getElementById('DivergingCenterRail');
    var x1 = parseFloat(track.getAttributeNS(null, 'x1'));
    var y1 = parseFloat(track.getAttributeNS(null, 'y1'));
    var x2 = parseFloat(track.getAttributeNS(null, 'x2'));
    var y2 = parseFloat(track.getAttributeNS(null, 'y2'));

    turnoutPos = x1;

    var x = x2 - x1;
    var y = y2 - y1;

    diveringTrackAngle = Math.atan(y/x);
}




function moveLocoOrCar(item, pos)
{
    var x = pos;
    var y = 0;
    var rotate = 0;
    if (selectDivergedTrack && (pos > turnoutPos)) {
        var posAfterTurnout = pos - turnoutPos;
        rotate = diveringTrackAngle * 360 / 2 / Math.PI;
        x = turnoutPos + posAfterTurnout * Math.cos(diveringTrackAngle);
        y = posAfterTurnout * Math.sin(diveringTrackAngle);
    }
    var data = "translate("+x+","+(y+200)+") scale(0.3) rotate("+rotate+")";
    item.setAttribute("transform", data);
}



function checkSensors()
{
    var sensorTriggered = false;
    sensorTriggered = (((locoPos-locoLength/2) <= sensor1_Pos) && ((locoPos+locoLength/2) >= sensor1_Pos));
    sensorTriggered |= (((carPos-carLength/2) <= sensor1_Pos) && ((carPos+carLength/2) >= sensor1_Pos));

    if (sensorTriggered) {
        // Sensor 1 triggered
        if (true ||    !sensor1_active) {
            sensor1_active = true;
            jmri.setSensor("IS_7_1", 2);
        }
    } else {
        // Sensor 1 not triggered
        if (true ||    sensor1_active) {
            sensor1_active = false;
            jmri.setSensor("IS_7_1", 4);
        }
    }


    sensorTriggered = false;
    if (!selectDivergedTrack) {
        sensorTriggered = (((locoPos-locoLength/2) <= sensor2_Pos) && ((locoPos+locoLength/2) >= sensor2_Pos));
        sensorTriggered |= (((carPos-carLength/2) <= sensor2_Pos) && ((carPos+carLength/2) >= sensor2_Pos));
    }
    if (sensorTriggered) {
        // Sensor 2 triggered
        if (true ||    !sensor2_active) {
            sensor2_active = true;
            jmri.setSensor("IS_7_2", 2);
        }
    } else {
        // Sensor 2 not triggered
        if (true ||    sensor2_active) {
            sensor2_active = false;
            jmri.setSensor("IS_7_2", 4);
        }
    }


    sensorTriggered = false;
    if (selectDivergedTrack) {
        sensorTriggered = (((locoPos-locoLength/2) <= sensor3_Pos) && ((locoPos+locoLength/2) >= sensor3_Pos));
        sensorTriggered |= (((carPos-carLength/2) <= sensor3_Pos) && ((carPos+carLength/2) >= sensor3_Pos));
    }
    if (sensorTriggered) {
        // Sensor 3 triggered
        if (true ||    !sensor3_active) {
            sensor3_active = true;
            jmri.setSensor("IS_7_3", 2);
        }
    } else {
        // Sensor 3 not triggered
        if (true ||    sensor3_active) {
            sensor3_active = false;
            jmri.setSensor("IS_7_3", 4);
        }
    }
}





window.setInterval(runTrain, 50);

function runTrain()
{
    jmri.setSensor("IS_7_2", "ACTIVE");


    if (throttleSpeed != 0)
    {
        if (carPos < turnoutPos) selectDivergedTrack = turnoutThrown;

        var speed = throttleSpeed;
        if (throttleForward) speed = -speed;

        locoPos += speed*2;
        carPos = locoPos + 150;

        var loco = document.getElementById('LocoHandle');
        moveLocoOrCar(loco, locoPos);

        var car = document.getElementById('CarHandle');
        moveLocoOrCar(car, carPos);
    } else {
        if ((carPos >= 591) && (carPos <= 858) && !selectDivergedTrack) {
            // Unload car
            carIsFilled = false;
            var carLoad = document.getElementById('CarLoad');
            carLoad.setAttribute("visibility", "hidden");
        }
    }

    // Check the sensors
    checkSensors();

    // Check the crane
    checkCrane();
}




function rotateCrane(value) {
    commandedCraneAngle = (craneMaxAngle - craneMinAngle) * value / 100 + craneMinAngle;
    if (commandedCraneAngle < craneMinAngle) commandedCraneAngle = craneMinAngle;
    if (commandedCraneAngle > craneMaxAngle) commandedCraneAngle = craneMaxAngle;
}


function liftLowerCrane(value) {
    commandedCraneUpDown = value;
    if (commandedCraneUpDown < 0) commandedCraneUpDown = 0;
    if (commandedCraneUpDown > 100) commandedCraneUpDown = 100;
}


function openCloseCraneBucket(value) {
    commandedCraneBucketOpenClosed = value;
    if (commandedCraneBucketOpenClosed < 2) commandedCraneBucketOpenClosed = 2;
    if (commandedCraneBucketOpenClosed > 100) commandedCraneBucketOpenClosed = 100;
}


function checkLoadingOfCar()
{
    // If here, the crane bucket is filled, but the bucket is opened to drop its coal

    // Check if crane bucket is close to the track
    if ((craneAngle < 0) || (craneAngle > 60)) return;

    // Calculate where the crane bucket are relative to the track
    // 857 = position of the car when the car is below the crane bucket and the crane arm is
    // perpendicular to the track.
    var cranePosRelativeToTrack = Math.sin((craneAngle-30) * 2 * Math.PI / 360) * 2 * 57 + 857;

    if (selectDivergedTrack && (Math.abs(carPos - cranePosRelativeToTrack) < carLength/3)) {
        carIsFilled = true;
        var carLoad = document.getElementById('CarLoad');
        carLoad.setAttribute("visibility", "visible");
    }
}


function checkCrane()
{
    var lastAngle = craneAngle;

    if (craneUpDown >= 80) {
        if (commandedCraneAngle < craneAngle) {
            craneAngle -= 1;
            if (craneAngle < commandedCraneAngle) craneAngle = commandedCraneAngle;
        }
        if (commandedCraneAngle > craneAngle) {
            craneAngle += 1;
            if (craneAngle > commandedCraneAngle) craneAngle = commandedCraneAngle;
        }
    }

    if (craneAngle != lastAngle) {
        var item = document.getElementById('CraneHandle');
        var data = "translate("+craneX+","+(craneY)+") scale(0.3) rotate("+craneAngle+")";
        item.setAttribute("transform", data);

        anglePercent = (craneAngle - craneMinAngle) / (craneMaxAngle - craneMinAngle) * 100;
        jmri.setMemory("IM_7_2", anglePercent);
    }



    var lastCraneUpDown = craneUpDown;
    if (commandedCraneUpDown < craneUpDown) {
        craneUpDown -= 1;
        if (craneUpDown < commandedCraneUpDown) craneUpDown = commandedCraneUpDown;
    }
    if (commandedCraneUpDown > craneUpDown) {
        craneUpDown += 1;
        if (craneUpDown > commandedCraneUpDown) craneUpDown = commandedCraneUpDown;
    }

    if (craneUpDown != lastCraneUpDown) {
        var item = document.getElementById('CraneUpDown');
        var data = "translate(0,0) rotate("+((100-craneUpDown)*1.80)+")";
        item.setAttribute("transform", data);

        jmri.setMemory("IM_7_4", craneUpDown);
    }



    var lastCraneBucketOpenClosed = craneBucketOpenClosed;
    if (commandedCraneBucketOpenClosed < craneBucketOpenClosed) {
        craneBucketOpenClosed -= 1;
        if (craneBucketOpenClosed < commandedCraneBucketOpenClosed) craneBucketOpenClosed = commandedCraneBucketOpenClosed;
        if (craneBucketFilled && (craneBucketOpenClosed < 50)) {
            checkLoadingOfCar();
            craneBucketFilled = false;
        }
    }
    if (commandedCraneBucketOpenClosed > craneBucketOpenClosed) {
        craneBucketOpenClosed += 1;
        if (craneBucketOpenClosed > commandedCraneBucketOpenClosed) craneBucketOpenClosed = commandedCraneBucketOpenClosed;
        if (!craneBucketFilled && (craneBucketOpenClosed > 50) && (craneUpDown < 20) && (anglePercent >= 22) && (anglePercent <= 48)) {
            craneBucketFilled = true;
        }
    }

    if (craneBucketOpenClosed != lastCraneBucketOpenClosed) {
        var item = document.getElementById('CraneBucket');
        var data = "translate(0,0) rotate("+((100-craneBucketOpenClosed)*1.80)+")";
        item.setAttribute("height", craneBucketOpenClosed);

        if (!craneBucketFilled) item.setAttribute("fill", "#4F81BD");
        else item.setAttribute("fill", "#948A54");

        jmri.setMemory("IM_7_6", craneBucketOpenClosed);
    }

}
