// Altitude preselection modes
var altPreselMode = {
    none: 0,
    auto: 1,
    manual: 2
};

// VS engage modes
var vsEngageMode = {
    none: 0,
    reset: 1,
    default: 2,
    current: 3
};

// Lateral modes
var lateralMode = {
    none: 0,
    roll: 1,
    hdg: 2,
    gps: 3,
    vor: 4,
    loc: 5,
    bc: 6,
    aprgps: 7,
    aprvor: 8,
    aprloc: 9,
    lvl: 10,
    cga: 11,
    clvl: 12
};

// Vertical modes
var verticalMode = {
    none: 0,
    pitch: 1,
    vs: 2,
    alt: 3,
    gs: 4,
    gp: 5,
    flc: 6,
    vnav: 7,
    cga: 8,
    clvl: 9
};

// Combined modes
var combinedMode = {
    none: 0,
    cga: 1,
    clvl: 2
};

// Target altitude phases
var selectedAltitudePhase = {
    none: 0,    // No ALTS
    engaged: 1, // Altitude diff is greater than alert threshold.
    alert: 2,   // Altitude diff is between alert and near thresholds.
    near: 3,    // Altitude diff is less than near threshold.
    ready: 4,   // Vertical mode is ALT and Altitude diff greater than the reached threshold.
    reached: 5  // Vertical mode is ALT and Altitude diff is less than reached threshold. Phase returns to none after a time out.
};

// Fp approach type
var approachType = {
    none: 0,
    gps: 1,
    vor: 2,
    ndb: 3,
    ils: 4,
    loc: 5,
    sdf: 6,
    lda: 7,
    vordme: 8,
    ndbdme: 9,
    rnav: 10,
    bc: 11
};

// Workaround to a sim issue when posting H events after restarting the aircraft
function postHEvent(event) {
    let useWatcher = SimVar.g_bUseWatcher;
    if(useWatcher)
        SimVar.g_bUseWatcher = false;
    SimVar.SetSimVarValue("H:" + event, "number", 0);
    if(useWatcher)
        SimVar.g_bUseWatcher = true;
}

class KAP140 extends BaseInstrument {
    constructor() {
        super();
        this.blinkCounter = 0;
        this.RightBlockReinitTime = 0;
        this.RightBlockCurrDisplay = 0;
        this.bAvionicsPowerOn = false;
        this.iTestingStep = -1;
        this.fCurrentStepDuration = 0.0;
        this.tTestingStepsTime = [2000, 1200, 3200, 4000, 3200];
        this.BaroMode = 0;
        this.baroIndex = 2;
    }
    get templateID() { return "KAP140"; }
    get instrumentAlias() { return "APGA"; }
    connectedCallback() {
        super.connectedCallback();
        RegisterViewListener("JS_LISTENER_KEYEVENT");
        this.PTDisplay = this.getChildById("PTDisplay");
        this.UPArrow = this.getChildById("UPArrow");
        this.DownArrow = this.getChildById("DownArrow");
        this.APdisplay = this.getChildById("APDisplay");
        this.LeftDisplayTop = this.getChildById("LeftDisplayTop");
        this.LeftDisplayBot = this.getChildById("LeftDisplayBot");
        this.MidDisplayTop = this.getChildById("MidDisplayTop");
        this.MidDisplayBot = this.getChildById("MidDisplayBot");
        this.LeftARM = this.getChildById("ARMLeft");
        this.MidARM = this.getChildById("ARMMid");
        this.RightBlock = this.getChildById("RightBlock");
        this.RightDisplayTop = this.getChildById("RightDisplayTop");
        this.AlertDisplay = this.getChildById("Alert");
        let parsedUrl = new URL(this.getAttribute("Url").toLowerCase());
        let baro = parsedUrl.searchParams.get("baro");
        this.baroIndex = baro ? parseInt(baro) : 2;
    }
    disconnectedCallback() {
        super.disconnectedCallback();
    }
    onInteractionEvent(_args) {
        if (this.isElectricityAvailable()) {
            let apOn = this.isAutopilotEngaged();
            switch (_args[0]) {
                case "KAP140_Push_AP":
                case "APGA_AP":
                    postHEvent("PMS50_APGA_AP_AP");
                    if (!apOn) {
                        setTimeout(()=>{
                            this.RightBlockReinitTime = 3000;
                            this.RightBlockCurrDisplay = 1;
                        }, 500);
                    }
                    break;
                case "KAP140_Push_HDG":
                case "APGA_HDG":
                    if (apOn)
                        postHEvent("PMS50_APGA_AP_HDG");
                    break;
                case "KAP140_Push_NAV":
                case "APGA_NAV":
                    if (apOn)
                        postHEvent("PMS50_APGA_AP_NAV");
                    break;
                case "KAP140_Push_APR":
                case "APGA_APR":
                    if (apOn)
                        postHEvent("PMS50_APGA_AP_APR");
                    break;
                case "KAP140_Push_REV":
                case "APGA_REV":
                    if (apOn)
                        postHEvent("PMS50_APGA_AP_REV");
                    break;
                case "KAP140_Push_ALT":
                case "APGA_ALT":
                    if (apOn) {
                        postHEvent("PMS50_APGA_AP_ALT");
                        if(this.verticalMode == verticalMode.alt) {
                            // Display VS for 3 seconds when leaving ALT mode
                            setTimeout(()=>{
                                this.RightBlockReinitTime = 3000;
                                this.RightBlockCurrDisplay = 1;
                            }, 500);
                        }
                    }
                    break;
                case "KAP140_Push_UP":
                case "APGA_UP":
                    if(this.verticalMode == verticalMode.vs) {
                        if (this.RightBlockCurrDisplay != 1) {
                            // We just redisplay the VS if it was not already displayed
                            // This allows viewing the current value without modifying it
                            this.RightBlockCurrDisplay = 1;
                        }
                        else {
                            // If already displayed, we send the order
                            postHEvent("PMS50_APGA_AP_UP");
                        }
                        // Reset the time out to 3 seconds
                        this.RightBlockReinitTime = 3000;
                    }
                    else if(this.verticalMode == verticalMode.alt)
                        postHEvent("PMS50_APGA_AP_UP");
                    break;
                case "KAP140_Push_DN":
                case "APGA_DOWN":
                    if(this.verticalMode == verticalMode.vs) {
                        if (this.RightBlockCurrDisplay != 1) {
                            // We just redisplay the VS if it was not already displayed
                            // This allows viewing the current value without modifying it
                            this.RightBlockCurrDisplay = 1;
                        }
                        else {
                            // If already displayed, we send the order
                            postHEvent("PMS50_APGA_AP_DOWN");
                        }
                        // Reset the time out to 3 seconds
                        this.RightBlockReinitTime = 3000;
                    }
                    else if(this.verticalMode == verticalMode.alt)
                        postHEvent("PMS50_APGA_AP_DOWN");
                    break;
                case "KAP140_Push_BARO":
                    this.RightBlockReinitTime = 3000;
                    this.RightBlockCurrDisplay = 2;
                    break;
                case "KAP140_Long_Push_BARO":
                    this.RightBlockReinitTime = 3000;
                    this.RightBlockCurrDisplay = 2;
                    this.BaroMode = 1 - this.BaroMode;
                    break;
                case "KAP140_Push_ARM":
                case "APGA_ARM":
                    if (apOn)
                        postHEvent("PMS50_APGA_AP_ARM");
                    break;
                case "KAP140_Knob_Outer_INC":
                case "KAP140_Knob_Outer_DEC":
                case "KAP140_Knob_Inner_INC":
                case "KAP140_Knob_Inner_DEC":
                case "APGA_SEL_ALT_SMALL_INC":
                case "APGA_SEL_ALT_SMALL_DEC":
                case "APGA_SEL_ALT_LARGE_INC":
                case "APGA_SEL_ALT_LARGE_DEC":
                    if (this.RightBlockCurrDisplay == 1) {
                        this.RightBlockReinitTime = 0;
                        this.RightBlockCurrDisplay = 0;
                    }
                    if (this.RightBlockCurrDisplay == 2) {
                        this.RightBlockReinitTime = 3000;
                        switch (_args[0]) {
                            case "KAP140_Knob_Inner_INC":
                            case "KAP140_Knob_Outer_INC":
                            case "APGA_SEL_ALT_SMALL_INC":
                            case "APGA_SEL_ALT_LARGE_INC":
                                SimVar.SetSimVarValue("K:KOHLSMAN_INC", "number", this.baroIndex);
                                break;
                            case "KAP140_Knob_Outer_DEC":
                            case "KAP140_Knob_Inner_DEC":
                            case "APGA_SEL_ALT_SMALL_DEC":
                            case "APGA_SEL_ALT_LARGE_DEC":
                                SimVar.SetSimVarValue("K:KOHLSMAN_DEC", "number", this.baroIndex);
                                break;
                        }
                    }
                    else {
                        switch (_args[0]) {
                            case "KAP140_Knob_Outer_INC":
                            case "APGA_SEL_ALT_LARGE_INC":
                                postHEvent("PMS50_APGA_SEL_ALT_LARGE_INC");
                                break;
                            case "KAP140_Knob_Outer_DEC":
                            case "APGA_SEL_ALT_LARGE_DEC":
                                postHEvent("PMS50_APGA_SEL_ALT_LARGE_DEC");
                                break;
                            case "KAP140_Knob_Inner_INC":
                            case "APGA_SEL_ALT_SMALL_INC":
                                postHEvent("PMS50_APGA_SEL_ALT_SMALL_INC");
                                break;
                            case "KAP140_Knob_Inner_DEC":
                            case "APGA_SEL_ALT_SMALL_DEC":
                                postHEvent("PMS50_APGA_SEL_ALT_SMALL_DEC");
                                break;
                        }
                    }
                    break;
            }
        }
    }

    Update() {
        super.Update();
        if (this.isElectricityAvailable()) {
            this.blinkCounter = (this.blinkCounter + this.deltaTime) % 1000000;
            if (!this.bAvionicsPowerOn) {
                this.bAvionicsPowerOn = true;
                this.iTestingStep = 0;
                this.fCurrentStepDuration = this.tTestingStepsTime[this.iTestingStep] + Math.random() * 500;
                LaunchFlowEvent("AUTOPILOT_PREFLIGHT_CHECK_START");
                SimVar.SetSimVarValue("L:AutopilotPreflightCheckCompleted", "Boolean", 0);
            }
            else {
                if (this.iTestingStep >= 0) {
                    this.fCurrentStepDuration -= this.deltaTime;
                    if (this.fCurrentStepDuration <= 0.0) {
                        this.fCurrentStepDuration = this.tTestingStepsTime[this.iTestingStep++] + Math.random() * 500;
                        if (this.iTestingStep >= this.tTestingStepsTime.length) {
                            this.iTestingStep = -1;
                            LaunchFlowEvent("AUTOPILOT_PREFLIGHT_CHECK_OVER");
                            SimVar.SetSimVarValue("L:AutopilotPreflightCheckCompleted", "Boolean", 1);
                            this.HideEveryDisplay();
                            this.RightDisplayTop.style.visibility = "visible";
                            this.LeftDisplayTop.style.visibility = "visible";
                            this.LeftDisplayBot.style.visibility = "visible";
                            this.MidDisplayTop.style.visibility = "visible";
                            this.MidDisplayBot.style.visibility = "visible";
                            this.RightDisplayTop.style.visibility = "visible";
                            this.RightDisplayTop.classList.remove("alignLeft");
                        }
                    }
                }
            }
            if (this.iTestingStep == this.tTestingStepsTime.length - 1) {
                this.ShowEveryDisplay();
                diffAndSetText(this.LeftDisplayTop, "888");
                diffAndSetText(this.LeftDisplayBot, "888");
                diffAndSetText(this.MidDisplayTop, "888");
                diffAndSetText(this.MidDisplayBot, "888");
                diffAndSetText(this.RightDisplayTop, "88.888");
                return;
            }
            else if (this.iTestingStep > -1) {
                this.HideEveryDisplay();
                this.MidDisplayTop.style.visibility = "visible";
                diffAndSetText(this.MidDisplayTop, "PFT");
                this.RightDisplayTop.style.visibility = "visible";
                diffAndSetText(this.RightDisplayTop, fastToFixed((this.iTestingStep + 1), 0));
                this.RightDisplayTop.classList.add("alignLeft");
                return;
            }

            // Update the current lateral mode
            this.lateralMode = SimVar.GetSimVarValue("L:PMS50_APGA_ACTIVE_LATERAL_MODE", "number");

            // Update the current vertical mode
            this.verticalMode = SimVar.GetSimVarValue("L:PMS50_APGA_ACTIVE_VERTICAL_MODE", "number");

            // Update the armed lateral mode
            this.armedLateralMode = SimVar.GetSimVarValue("L:PMS50_APGA_ARMED_LATERAL_MODE", "number");

            // Update the armed vertical mode
            this.armedVerticalMode = SimVar.GetSimVarValue("L:PMS50_APGA_ARMED_VERTICAL_MODE", "number");

            // Update the altitude phase
            this.selectedAltitudePhase = SimVar.GetSimVarValue("L:PMS50_APGA_SELECTED_ALTITUDE_PHASE", "number");

            // Autopilot annunciator
            this.APdisplay.style.visibility = this.isAutopilotEngaged() ? "visible" : "hidden";



            diffAndSetText(this.LeftDisplayTop, this.getActiveLateralModeForDisplay());
            var armedRoll = this.getArmedLateralModeForDisplay();
            diffAndSetText(this.LeftDisplayBot, armedRoll);
            if (armedRoll) {
                this.LeftARM.style.visibility = "visible";
            }
            else {
                this.LeftARM.style.visibility = "hidden";
            }
            diffAndSetText(this.MidDisplayTop, this.getActiveVerticalModeForDisplay());
            var armedPitch = this.getArmedVerticalModeForDisplay();
            diffAndSetText(this.MidDisplayBot, armedPitch);
            if (armedPitch) {
                this.MidARM.style.visibility = "visible";
            }
            else {
                this.MidARM.style.visibility = "hidden";
            }
//            SimVar.SetSimVarValue("L:KAP140_BARO_Display", "Bool", this.RightBlockCurrDisplay == 2 ? 1 : 0);
            if (this.RightBlockReinitTime > 0) {
                this.RightBlockReinitTime -= this.deltaTime;
                if (this.RightBlockReinitTime <= 0) {
                    this.RightBlockReinitTime = 0;
                    this.RightBlockCurrDisplay = 0;
                }
                else if (this.RightBlockCurrDisplay == 1) {
                    diffAndSetAttribute(this.RightBlock, "state", "FPM");
                    diffAndSetText(this.RightDisplayTop, this.getVerticalSpeedSelectedForDisplay());
                }
                else if (this.RightBlockCurrDisplay == 2) {
                    if (this.BaroMode == 0) {
                        diffAndSetAttribute(this.RightBlock, "state", "HPA");
                        diffAndSetText(this.RightDisplayTop, this.getBaroHPa());
                    }
                    else {
                        diffAndSetAttribute(this.RightBlock, "state", "INHG");
                        diffAndSetText(this.RightDisplayTop, this.getBaroInHg());
                    }
                }
            }
            if (this.RightBlockCurrDisplay == 0) {
                diffAndSetAttribute(this.RightBlock, "state", "FT");
                diffAndSetText(this.RightDisplayTop, this.getAltitudeSelectedForDisplay());
            }

            // Alert display depends of altitude diff
            // also displayed until time out when reaching altitude
            var differenceToObj = this.getAltitudeDifference();
            if ((differenceToObj >= 200 && differenceToObj <= 1000) || this.selectedAltitudePhase == selectedAltitudePhase.reached) {
                this.AlertDisplay.style.visibility = "visible";
            }
            else {
                this.AlertDisplay.style.visibility = "hidden";
            }
            // Adjust the trim display
            let neededTrim = SimVar.GetSimVarValue("L:PMS50_APGA_NEED_TRIM_VALUE", "feet per minute");
            let hidden = (this.blinkGetState(600, 300) ? false : true);
            if (neededTrim < -100 && this.verticalMode != verticalMode.none && this.verticalMode != verticalMode.pitch) {
                this.PTDisplay.classList.toggle('hide', hidden);
                this.UPArrow.classList.toggle('hide', hidden);
                this.DownArrow.style.visibility = "hidden";
            }
            else if (neededTrim > 100 && this.verticalMode != verticalMode.none && this.verticalMode != verticalMode.pitch) {
                this.PTDisplay.classList.toggle('hide', hidden);
                this.UPArrow.style.visibility = "hidden";
                this.DownArrow.classList.toggle('hide', hidden);
            }
            else {
                this.PTDisplay.style.visibility = "hidden";
                this.UPArrow.style.visibility = "hidden";
                this.DownArrow.style.visibility = "hidden";
            }
        }
        else {
            if (this.bAvionicsPowerOn) {
                this.HideEveryDisplay();
                this.bAvionicsPowerOn = false;
            }
        }
    }
    HideEveryDisplay() {
        this.LeftDisplayTop.style.visibility = "hidden";
        this.LeftDisplayBot.style.visibility = "hidden";
        this.MidDisplayTop.style.visibility = "hidden";
        this.MidDisplayBot.style.visibility = "hidden";
        this.RightDisplayTop.style.visibility = "hidden";
        this.APdisplay.style.visibility = "hidden";
        this.LeftARM.style.visibility = "hidden";
        this.MidARM.style.visibility = "hidden";
        this.AlertDisplay.style.visibility = "hidden";
        this.PTDisplay.style.visibility = "hidden";
        this.UPArrow.style.visibility = "hidden";
        this.DownArrow.style.visibility = "hidden";
        diffAndSetAttribute(this.RightBlock, "state", "NONE");
    }
    ShowEveryDisplay() {
        this.LeftDisplayTop.style.visibility = "visible";
        this.LeftDisplayBot.style.visibility = "visible";
        this.MidDisplayTop.style.visibility = "visible";
        this.MidDisplayBot.style.visibility = "visible";
        this.RightDisplayTop.style.visibility = "visible";
        this.APdisplay.style.visibility = "visible";
        this.LeftARM.style.visibility = "visible";
        this.MidARM.style.visibility = "visible";
        this.AlertDisplay.style.visibility = "visible";
        this.PTDisplay.style.visibility = "visible";
        this.UPArrow.style.visibility = "visible";
        this.DownArrow.style.visibility = "visible";
        diffAndSetAttribute(this.RightBlock, "state", "ALL");
    }

    // Get the active lateral mode for display purpose
    getActiveLateralModeForDisplay() {
        // The LVL mode is displayed as ROLL mode in the KAP140
        // The ROLL mode acts as a winf lvele
        if(this.lateralMode == lateralMode.roll || this.lateralMode == lateralMode.lvl)
            return "ROL";
        if(this.lateralMode == lateralMode.hdg)
            return "HDG";
        if(this.lateralMode == lateralMode.gps || this.lateralMode == lateralMode.vor || this.lateralMode == lateralMode.loc)
            return "NAV";
        if(this.lateralMode == lateralMode.aprgps || this.lateralMode == lateralMode.aprvor || this.lateralMode == lateralMode.aprloc)
            return "APR";
        if(this.lateralMode == lateralMode.bc)
            return "REV";
        return "";
    }

    // Get the active vertical mode for display purpose
    getActiveVerticalModeForDisplay() {
        if(this.verticalMode == verticalMode.vs)
            return "VS";
        if(this.verticalMode == verticalMode.alt)
            return "ALT";
        if(this.verticalMode == verticalMode.gs || this.verticalMode == verticalMode.gp)
            return "GS";
        return "";
    }

    // Get the armed lateral mode for display purpose
    getArmedLateralModeForDisplay() {
        if(this.armedLateralMode == lateralMode.bc)
            return "REV";
        if(this.armedLateralMode == lateralMode.gps || this.armedLateralMode == lateralMode.vor || this.armedLateralMode == lateralMode.loc)
            return "NAV";
        if(this.armedLateralMode == lateralMode.aprgps || this.armedLateralMode == lateralMode.aprvor || this.armedLateralMode == lateralMode.aprloc)
            return "APR";
        return "";
    }

    // Get the armed vertical mode for display purpose
    getArmedVerticalModeForDisplay() {
        if(this.armedVerticalMode == verticalMode.gs || this.armedVerticalMode == verticalMode.gp)
            return "GS";
        if(this.armedVerticalMode == verticalMode.alt)
            return "ALT";
        return "";
    }

    // Get the selected altitude for display purpose
    getAltitudeSelectedForDisplay() {
        // Sim value if auto arm and internal value for manual arm
        let altitudeSelected = SimVar.GetSimVarValue("L:PMS50_APGA_SELECTED_ALTITUDE", "feet");
        return (fastToFixed(altitudeSelected, 0)).replace(/\d+(?=(\d{3}))/, '$&,');
    }

    // Format the captured altitude for display purpose
    getCapturedAltitudeForDisplay() {
        if(this.capturedAltitude >= 0)
            return (fastToFixed(this.capturedAltitude, 0)).replace(/\d+(?=(\d{3}))/, '$&,');
        else
            return "";
    }

    // Get the selected VS for display purpose
    getVerticalSpeedSelectedForDisplay() {
        return (fastToFixed(SimVar.GetSimVarValue("L:PMS50_APGA_SELECTED_VS", "feet/minute"), 0)).replace(/\d+(?=(\d{3}))/, '$&,');
    }

    isAutopilotEngaged() {
        return SimVar.GetSimVarValue("L:PMS50_APGA_AP", "Bool");
    }
    getBaroHPa() {
        return (fastToFixed(SimVar.GetSimVarValue("KOHLSMAN SETTING MB:" + this.baroIndex , "Millibars"), 0)).replace(/\d+(?=(\d{3}))/, '$&,');
    }
    getBaroInHg() {
        return fastToFixed(SimVar.GetSimVarValue("KOHLSMAN SETTING HG:" + this.baroIndex , "inHg"), 2);
    }
    getAltitudeDifference() {
        return Math.abs(SimVar.GetSimVarValue("INDICATED ALTITUDE:" + this.baroIndex , "feet") - SimVar.GetSimVarValue("L:PMS50_APGA_SELECTED_ALTITUDE", "feet"));
    }
    blinkGetState(_blinkPeriod, _duration) {
        return Math.round(this.blinkCounter / _duration) % (_blinkPeriod / _duration) == 0;
    }
}
registerInstrument("kap140-element", KAP140);
//# sourceMappingURL=KAP140.js.map