#Engine control class
# ie: var Eng = Engine.new(engine number);
var Engine = {
    new : func(eng_num){
        var m = { parents : [Engine]};
        m.OperatingOilTemp = 120;
        m.eng_num = eng_num;
        m.eng = props.globals.getNode("engines/engine["~eng_num~"]",1);
        m.n1 = m.eng.getNode("n1",1);
        m.n2 = m.eng.getNode("n2",1);
        m.rpm = m.eng.getNode("rpm",1);
        m.rpm.setDoubleValue(0);
        m.n2rpm = m.eng.getNode("n2rpm",1);
        m.n2rpm.setDoubleValue(0);
        m.egt_degf = m.eng.getNode("egt-degf",1);
        m.egt = m.eng.getNode("egt",1);
        m.egt.setDoubleValue(0);
        m.reverser_cmd = props.globals.getNode("controls/engines/engine["~eng_num~"]/reverser",1);
        m.reverser_cmd.setBoolValue(0);
        m.reverser = props.globals.getNode("controls/engines/engine["~eng_num~"]/reverser-act",1);
        m.throttle = props.globals.getNode("controls/engines/engine["~eng_num~"]/throttle-act",1);
        m.throttle.setDoubleValue(0);
        m.cutoff = props.globals.getNode("controls/engines/engine["~eng_num~"]/cutoff",1);
        m.cutoff.setBoolValue(1);
        m.fuel_out = props.globals.getNode("engines/engine["~eng_num~"]/no-fuel",1);
        m.fuel_out.setBoolValue(0);
        m.autostart = props.globals.getNode("controls/engines/autostart",1);
        m.autostart.setBoolValue(1);
        m.starterSwitch = props.globals.getNode("controls/engines/StartIgnition-knob["~eng_num~"]",1);
        m.starter = props.globals.getNode("controls/engines/engine["~eng_num~"]/starter",1);
        m.starterSystem = props.globals.getNode("systems/electrical/outputs/starter["~eng_num~"]",1);
        m.generator = props.globals.getNode("controls/electric/engine["~eng_num~"]/generator",1);
        m.fuel_pph=m.eng.getNode("fuel-flow_pph",1);
        m.fuel_pph.setDoubleValue(0);
        m.fuel_gph=m.eng.getNode("fuel-flow-gph",1);
        m.hpump=props.globals.getNode("systems/hydraulics/pump-psi["~eng_num~"]",1);
        m.running = props.globals.getNode("engines/engine["~eng_num~"]/run",1);
        m.running.setBoolValue(0);
        m.hpump.setDoubleValue(0);
        m.apu = props.globals.getNode("controls/APU", 1);
        m.apu_knob = m.apu.getNode("off-start-run", 1);
        m.apu_status = m.apu.getNode("apu_status", 1);
        m.apu_status.setValue(0);
        m.apu_gen_switch = m.apu.getNode("apu-gen-switch", 1);
        m.apu_gen_switch.setBoolValue(0);
        m.apu_running = m.apu.getNode("run", 1);
        m.apu_running.setBoolValue(0);
        m.oilTemperatureDegc=m.eng.getNode("oil-temperature-degc",1);
        var envirT = getprop("environment/temperature-degc") or 0.00;
        m.oilTemperatureDegc.setDoubleValue(envirT);
        m.oilPressurePsi=m.eng.getNode("oil-pressure-psi",1);
        m.oilPressurePsi.setDoubleValue(0);
        m.oilQuantity=m.eng.getNode("oil-quantity",1);
        m.oilQuantity.setDoubleValue(17);

        m.last_update_time = getprop("sim/time/elapsed-sec");
        return m;
    },
    updateOilTemp : func {
        var oilHeatFactor=0.2;
        var oilCoolFactor=0.1;
        var envirT = getprop("environment/temperature-degc") or 0.00;
        var currentElapseTime = getprop("sim/time/elapsed-sec");
        var deltaTime = currentElapseTime - me.last_update_time;
        var currentFuelFlow = me.fuel_pph.getValue();
        if (currentFuelFlow > 0 and me.oilTemperatureDegc.getValue() < me.OperatingOilTemp) {
            me.oilTemperatureDegc.setDoubleValue(me.oilTemperatureDegc.getValue() + oilHeatFactor*currentFuelFlow*(deltaTime));
        }
        else {
            if (me.oilTemperatureDegc.getValue() > envirT) {
                me.oilTemperatureDegc.setDoubleValue(me.oilTemperatureDegc.getValue() - oilCoolFactor*(deltaTime));
            }
            else {
                me.oilTemperatureDegc.setDoubleValue(me.oilTemperatureDegc.getValue() + oilCoolFactor*(deltaTime));
            }
        }
        me.last_update_time = currentElapseTime;
    },
    updateOilPressure : func(n2rpm) {
        if (n2rpm < 20) {
            me.oilPressurePsi.setDoubleValue(5.6*math.sqrt(n2rpm));
        }
        else 
        {
            me.oilPressurePsi.setDoubleValue(0.3*n2rpm+19);
        }
    },
    updateOilQuantity : func(oilPressure) {
        me.oilQuantity.setDoubleValue(17 - (oilPressure/60)*2);
    },
#### update ####
    update : func {
        me.updateOilTemp();
        me.updateOilPressure(me.n2rpm.getValue());
        me.updateOilQuantity(me.oilPressurePsi.getValue());
        if(me.fuel_out.getBoolValue() or me.cutoff.getBoolValue())
        {
            me.fuel_pph.setDoubleValue(0);
            me.running.setBoolValue(0);
            me.egt.setDoubleValue(me.egt_degf.getValue());
        }
        if(getprop("sim/flight-model") == "yasim")
        {
            if(me.running.getBoolValue())
            {
                if(me.starterSwitch.getValue() == -1)
                {
                    settimer(func { me.starterSwitch.setValue(0);}, 0.3);
                }
                me.rpm.setValue(me.n1.getValue());
                me.n2rpm.setValue(me.n2.getValue());
                if(me.throttle.getValue() == 0)
                {
                    var reverser_cmd = me.reverser_cmd.getValue();
                    if(reverser_cmd != me.reverser.getValue())
                    {
                        me.reverser.setValue(reverser_cmd);
                    }
                }
                me.egt.setDoubleValue(me.egt_degf.getValue());
                var v_pph = (me.fuel_gph.getValue() * getprop("consumables/fuel/tank/density-ppg") / 1000);
                if(v_pph < 1.2)
                {
                    me.idle_ff();
                    v_pph=1.2;
                }
                else
                    v_pph = v_pph + 1.2 / (1 + v_pph);
                me.fuel_pph.setValue(v_pph);
                var v_egt = me.egt_degf.getValue() - 64;
                if(v_egt > 0)
                {
                    v_egt = 270 - v_egt/4;
                }
                else
                {
                    v_egt = 270;
                }
                   me.egt.setDoubleValue(me.egt_degf.getValue() + v_egt);
            }
            else
            {
                if(me.starterSwitch.getValue() == -1)
                {
                    if(getprop("controls/electric/APU-generator")
                            or getprop("engines/engine[0]/run")
                            or getprop("engines/engine[1]/run")
                            or getprop("controls/electric/external-power")
                            or getprop("controls/electric/external-power[1]")
                    )
                    {
                        me.spool_up();
                    }
                    else
                    {
                        settimer(func { me.starterSwitch.setValue(0);}, 0.3);
                    }
                }else{
                    var tmprpm = me.rpm.getValue();
                    tmprpm -= getprop("sim/time/delta-realtime-sec") * 1.2;
                    if(tmprpm < 0.0) tmprpm = 0;
                    me.rpm.setValue(tmprpm);
                    me.n2rpm.setValue(1.3*math.sqrt(tmprpm) * 12.65);
                }
            }
            var hpsi =me.rpm.getValue();
            if(hpsi>60)
                hpsi = 60;
            me.hpump.setValue(hpsi);
        }
        if(getprop("sim/flight-model") == "jsb")
        {
            if(me.starterSwitch.getValue() == -1)
            {
                me.starter.setValue(1);
            }
        }

        if(vmodel == "-200LR")
        {
            setprop("consumables/fuel/tank[3]/selected",
                (getprop("consumables/fuel/tank[3]/level-gal_us") > 0)
                and (getprop("controls/fuel/tank[1]/boost-pump[0]") or getprop("controls/fuel/tank[1]/boost-pump[1]")));
            setprop("consumables/fuel/tank[4]/selected",
                (getprop("consumables/fuel/tank[4]/level-gal_us") > 0)
                and (getprop("controls/fuel/tank[1]/boost-pump[0]") or getprop("controls/fuel/tank[1]/boost-pump[1]")));
            setprop("consumables/fuel/tank[5]/selected",
                (getprop("consumables/fuel/tank[5]/level-gal_us") > 0)
                and (getprop("controls/fuel/tank[1]/boost-pump[0]") or getprop("controls/fuel/tank[1]/boost-pump[1]")));
            setprop("consumables/fuel/tank[1]/selected", ((getprop("consumables/fuel/tank[3]/level-gal_us") < 30)
                and (getprop("consumables/fuel/tank[4]/level-gal_us") < 30)
                and (getprop("consumables/fuel/tank[5]/level-gal_us") < 30)
                and (getprop("consumables/fuel/tank[1]/level-gal_us") > 0)
                and (getprop("controls/fuel/tank[1]/boost-pump[0]") or getprop("controls/fuel/tank[1]/boost-pump[1]"))));
            setprop("consumables/fuel/tank[0]/selected", ((getprop("consumables/fuel/tank[3]/level-gal_us") < 30)
                and (getprop("consumables/fuel/tank[4]/level-gal_us") < 30)
                and (getprop("consumables/fuel/tank[5]/level-gal_us") < 30)
                and (getprop("consumables/fuel/tank[1]/level-gal_us") < 50)
                and (getprop("consumables/fuel/tank[0]/level-gal_us") > 0.1)
                and (getprop("controls/fuel/tank[0]/boost-pump[0]") or getprop("controls/fuel/tank[0]/boost-pump[1]"))));
            setprop("consumables/fuel/tank[2]/selected", ((getprop("consumables/fuel/tank[3]/level-gal_us") < 30)
                and (getprop("consumables/fuel/tank[4]/level-gal_us") < 30)
                and (getprop("consumables/fuel/tank[5]/level-gal_us") < 30)
                and (getprop("consumables/fuel/tank[1]/level-gal_us") < 50)
                and (getprop("consumables/fuel/tank[2]/level-gal_us") > 0.1)
                and (getprop("controls/fuel/tank[2]/boost-pump[0]") or getprop("controls/fuel/tank[2]/boost-pump[1]"))));
        }
        else
        {
            setprop("consumables/fuel/tank[1]/selected", ((getprop("consumables/fuel/tank[1]/level-gal_us") > 0)
                and (getprop("controls/fuel/tank[1]/boost-pump[0]") or getprop("controls/fuel/tank[1]/boost-pump[1]"))));
            setprop("consumables/fuel/tank[0]/selected", ((getprop("consumables/fuel/tank[1]/level-gal_us") < 50)
                and (getprop("consumables/fuel/tank[0]/level-gal_us") > 0.1)
                and (getprop("controls/fuel/tank[0]/boost-pump[0]") or getprop("controls/fuel/tank[0]/boost-pump[1]"))));
            setprop("consumables/fuel/tank[2]/selected", ((getprop("consumables/fuel/tank[1]/level-gal_us") < 50)
                and (getprop("consumables/fuel/tank[2]/level-gal_us") > 0.1)
                and (getprop("controls/fuel/tank[2]/boost-pump[0]") or getprop("controls/fuel/tank[2]/boost-pump[1]"))));
        }
        if(me.eng_num == 0)
        {
			if((getprop("consumables/fuel/tank[0]/level-gal_us") > 0) 
					or (getprop("consumables/fuel/tank[1]/level-gal_us") > 0))
			{
				me.fuel_out.setBoolValue(0);
			}
			else
			{
				me.fuel_out.setBoolValue(1);
			}
		}
		else
		{
			if((getprop("consumables/fuel/tank[2]/level-gal_us") > 0) 
					or (getprop("consumables/fuel/tank[1]/level-gal_us") > 0))
			{
				me.fuel_out.setBoolValue(0);
			}
			else
			{
				me.fuel_out.setBoolValue(1);
			}
		}
        if(me.apu_knob.getValue() == 0)
        {
            me.apu_status.setValue(0);            # OFF
            me.apu_running.setValue(0);
        }
        elsif(me.apu_knob.getValue() == 1)
        {
            if((me.apu_running.getBoolValue() == 0)
                and (me.apu_status.getValue() == 0))
            {
                me.apu_status.setValue(1);        # ARM
            }
        }
        else
        {
            if(me.apu_status.getValue() == 1)    # ARM
            {
                me.apu_status.setValue(2);        # START
                settimer(func { me.apu_status.setValue(3);}, 20);
            }
            settimer(func { me.apu_knob.setValue(1);}, 0.3);
        }
        if(me.apu_status.getValue() == 3)
        {
            me.apu_running.setBoolValue(1);
            if (getprop("controls/electric/APU-generator") != 1)
                setprop("controls/electric/APU-generator", 1);
                setprop("systems/electrical/APB", 1);
        }
        else
        {
            me.apu_running.setBoolValue(0);
            if (getprop("controls/electric/APU-generator") != 0)
                setprop("controls/electric/APU-generator", 0);
                setprop("systems/electrical/APB", 0);
        }
        if(me.apu_running.getBoolValue() and (getprop("consumables/fuel/tank[0]/level-lbs") > 0))
        {
            setprop("consumables/fuel/tank[0]/level-gal_us", getprop("consumables/fuel/tank[0]/level-gal_us")-0.0006);
        }
        if(getprop("controls/lighting/cabin-lights") == 1
            and getprop("controls/electric/APU-generator") == 0
            and getprop("controls/electric/engine[0]/generator") == 0
            and getprop("controls/electric/engine[1]/generator") == 0
            and getprop("controls/electric/battery-switch") == 0)
        {
            Shutdown();
        }
    },

    spool_up : func {
        var rpminc = 0;
        var tmprpm = me.rpm.getValue();
        var v_pph = 0;
        if(!me.fuel_out.getBoolValue() and !me.cutoff.getBoolValue())
        {
            v_pph = 1.2;
            me.idle_ff();
            if(tmprpm <10)
            {
                rpminc = 0.5;
            }
            else
            {
                rpminc = 0.8;
            }
            if(tmprpm >= me.n1.getValue())
            {
                controls.click(1);
                me.starterSwitch.setValue(0);
                me.running.setBoolValue(1);
                setprop("controls/lighting/cabin-lights",1);
                setprop("controls/lighting/strobe",1);
            }
            if(tmprpm > 0)
            {
                var v_egt = tmprpm * 270 / 18.5 + me.egt_degf.getValue();
                me.egt.setDoubleValue(v_egt);
            }
        }
        else
        {
            if(tmprpm <= 5)
            {
                rpminc = 0.1;
            }
        }
        tmprpm += getprop("sim/time/delta-realtime-sec") * rpminc;
        me.rpm.setValue(tmprpm);
        me.n2rpm.setValue(1.2*math.sqrt(tmprpm) * 12.65);
        me.fuel_pph.setValue(v_pph);
    },
# This function could be removed if FG fuel flow program is fixed to consume fuel when engine idle.
    idle_ff : func{
        var v_consume = 0.001;
        if(me.eng_num == 0)
        {
            if(getprop("consumables/fuel/tank[0]/selected")) 
            {
                setprop("consumables/fuel/tank[0]/level-gal_us", getprop("consumables/fuel/tank[0]/level-gal_us")- v_consume);
            }
            elsif(getprop("consumables/fuel/tank[1]/selected"))
            {
                setprop("consumables/fuel/tank[1]/level-gal_us", getprop("consumables/fuel/tank[1]/level-gal_us")- v_consume);
            }
            if(getprop("consumables/fuel/tank[0]/selected") or getprop("consumables/fuel/tank[1]/selected"))
            {
                me.fuel_out.setBoolValue(0);
            }
            else
            {
                me.fuel_out.setBoolValue(1);
            }
        }
        else
        {
            if(getprop("consumables/fuel/tank[2]/selected")) 
            {
                setprop("consumables/fuel/tank[2]/level-gal_us", getprop("consumables/fuel/tank[2]/level-gal_us")- v_consume);
            }
            elsif(getprop("consumables/fuel/tank[1]/selected"))
            {
                setprop("consumables/fuel/tank[1]/level-gal_us", getprop("consumables/fuel/tank[1]/level-gal_us")- v_consume);
            }
            if(getprop("consumables/fuel/tank[2]/selected") or getprop("consumables/fuel/tank[1]/selected"))
            {
                me.fuel_out.setBoolValue(0);
            }
            else
            {
                me.fuel_out.setBoolValue(1);
            }
        }
    },

};
