// We initialize the global simvar variable because otherwise in MSFS 2024, the BaseInstrument constructor fails 
var simvar = null;
class IngamePanelCustomPanel extends GTN750 {
    get instrumentAlias() { return "GTN750_PANEL"; }
    constructor() {
        super(...arguments);
        this._updatePanel = 0;
        this.isPanel = true;
        this.isCockpitCamera = null;
        this.mouseIn = false;
        this.resizeCounter = 0;
        this.showWidth = false;
        this.standby = false;
        this.debugPanel = false;
    }
    connectedCallback() {
        // Init all after some time out for things to be in place
        setTimeout(() => {
            super.connectedCallback();
            this.ingameUi = this.querySelector('ingame-ui');
            this.ingameUi.classList.add("hideWidth");
            // This is to prevent a bug that send events to the pnael even if the mouse is outside
            // See also GTN750_base
            this.ingameUi.addEventListener("mouseenter", this.onMouseEnter.bind(this));
            this.ingameUi.addEventListener("mouseleave", this.onMouseLeave.bind(this));
            this.mainframeGtn = this.getChildById("MainframeGtn");
            this.ingameUiheader = this.querySelector('ingame-ui-header');

            // We override the close button in order to set the running variable to false
            this.closeButton = this.ingameUiheader.querySelector('.Close');
            this.closeButton.replaceWith(this.closeButton.cloneNode(true));
            this.closeButton = this.ingameUiheader.querySelector('.Close');
            this.closeButton.addEventListener("OnValidate", () => {
                SimVar.SetSimVarValue("L:PANEL_GTN750_RUNNING", "bool", false);
                this.ingameUi.closePanel();
            });

            this.headerButtonElement = this.querySelector(".wrap");
//            this.displayHeader = false;
            this.preventResize = true;
            // Button for turning to minimize
            this.makeButton(this.getChildById("RadioPartLeftImg"), this.minimize.bind(this));

            // Move drag and drop
            this.dragDropHandler = new DragDropHandler(this.ingameUi, {
                dragElement: this.getChildById("RadioPartLeftText"),
                handleByGame: this.ingameUi.handleByGame
            });
            this.dragDropHandler.canBeDragged = true;
            this.dragDropHandler.OnDragStart(() => {
                this.ingameUi.isDragging = true;
                this.preventMinimize = true;
                if (this.ingameUi.attached) {
                    this.ingameUi.detachPanel();
                }
            });
            this.dragDropHandler.OnDragUpdate(() => {
                this.ingameUi.sendRect();
            });
            this.dragDropHandler.OnDragEnd(() => {
                this.ingameUi.isDragging = false;
                setTimeout(() => {
                    this.preventMinimize = false;
                }, 500);
                if (this.ingameUi.attached) {
                    this.ingameUi.detachPanel();
                }
            });
            // Also for standby
            this.dragDropHandlerStandby = new DragDropHandler(this.ingameUi, {
                dragElement: this.getChildById("standby"),
                handleByGame: this.ingameUi.handleByGame
            });
            this.dragDropHandlerStandby.canBeDragged = true;
            this.dragDropHandlerStandby.OnDragStart(() => {
                this.ingameUi.isDragging = true;
                this.preventMinimize = true;
                if (this.ingameUi.attached) {
                    this.ingameUi.detachPanel();
                }
            });
            this.dragDropHandlerStandby.OnDragUpdate(() => {
                this.ingameUi.sendRect();
            });
            this.dragDropHandlerStandby.OnDragEnd(() => {
                this.ingameUi.isDragging = false;
                setTimeout(() => {
                    this.preventMinimize = false;
                }, 500);
                if (this.ingameUi.attached) {
                    this.ingameUi.detachPanel();
                }
            });


            // Manage resize event and keyboard listener
            setTimeout(() => {
                window.addEventListener("resize", this.onResize.bind(this));
                window.addEventListener("keydown", this.onKeydown.bind(this));
                window.addEventListener("mouseenter", this.onMouseEnter.bind(this));
                window.addEventListener("mouseleave", this.onMouseLeave.bind(this));
                SimVar.SetSimVarValue("L:PANEL_GTN750_RUNNING", "bool", true);
                SimVar.SetSimVarValue("L:PANEL_GTN750_RESIZE_COUNTER", "number", this.resizeCounter);
                    // reload try to keep the page
                if(SimVar.GetSimVarValue("L:PANEL_GTN750_RELOAD", "bool")) {
                    // This is a reload after a resize
                    // We must switch to the correct page
                    let group = this.dataStore.get("PanelLastPageGroup", "HOME");
                    let page = this.dataStore.get("PanelLastPage", "MENU_HOME");
                    this.SwitchToPageName(group, page);
                    this.mouseIn = true;
                }
                SimVar.SetSimVarValue("L:PANEL_GTN750_RELOAD", "bool", false);
                // Do the initial resize
                setTimeout(() => {
                    this.preventResize = false;
                    this.setSize();
                }, 2000);
            }, 2000);
        }, 5000);   // Increase this time with the G1000 if issues when loading the world map FP
    }
    onMouseEnter() {
        this.mouseIn = true;
    }
    onMouseLeave() {
        this.mouseIn = false;
    }
    onKeydown(e) {
        // Shift + Ctrl + S toggle panel visibility
        if (e.shiftKey && e.ctrlKey && e.which == 83) {
            let camstate = SimVar.GetSimVarValue("A:CAMERA STATE", "number");
            // We don't toggle if the panel is extern
            if(!this.ingameUi.extern) {
                this.toggleVisibility();
                // SHIFT + CTRL + S
                e.preventDefault();
            }
        }
    }
    toggleVisibility() {
        if(!this.ingameUi.extern) {
            this.ingameUi.visible = !this.ingameUi.visible;
            this.ingameUi.active = this.ingameUi.visible;
        }
    }
    onCockpitCameraChanged() {
        // When switching to external camera, we hide the panel
        // The user can display it again with Shift + Ctrl + S
        if(this.isCockpitCamera) {
            // We changed back to cockpit camera
            // let's restore the in cockpit panel state
            if(this.savedPanelVisibility) {
                if(!this.ingameUi.extern) {
                    this.ingameUi.visible = this.savedPanelVisibility;
                    this.ingameUi.active = this.savedPanelVisibility;
                }
                this.savedPanelVisibility = null;
            }
        }
        else {
            // We have switched to externalview
            // We save the cockpit panel state
            if(!this.ingameUi.extern) {
                this.savedPanelVisibility = this.ingameUi.visible;
                this.ingameUi.visible = false;
                this.ingameUi.active = false;
            }
        }
    }

    // Classes that derive from BaseInstrument have an onUpdate method which appears to fire every X frames.
    // We need to override it here and call super so the GTN750 works as expected.
    onUpdate(args) {
        if(!this.isStarted) {
            diffAndSetAttribute(this.ingameUiheader, "style", "display: flex;");
            return;
        }
        this.panelInvisible = this.ingameUi.classList.contains("panelInvisible") || this.ingameUi.classList.contains("panelInactive") || this.ingameUi.classList.contains("minimized");
        this.panelExtern = this.ingameUi.classList.contains("extern");
        super.onUpdate(args);

        // Manage panel header and resize
        this._updatePanel++;
        if(this._updatePanel > 5) {
            this._updatePanel = 0;
            //If too small we display the header anyway
            if(this.ingameUi.getBoundingClientRect().height < 100)
                 this.displayHeader = true;
            else
                this.displayHeader = false;
            // else if(!this.StartedDisplayHeader)
            //     this.displayHeader = false;
//            this.setSize();
            if(this.ingameUiheader)
                diffAndSetAttribute(this.ingameUiheader, "style", "display: " + (this.displayHeader ? "flex" : "none") + ";");
        }
        // Check cockpit camera state changed
        let newCameraState = SimVar.GetSimVarValue("A:CAMERA STATE", "number");
        if(this.isCockpitCamera == null || this.isCockpitCamera != (newCameraState == 2)) {
            this.isCockpitCamera = (newCameraState == 2);
            this.onCockpitCameraChanged();
        }
    }
    doInit() {
        super.doInit();
        this.preventResize = false;
        this.setSize();
    }
    
    disconnectedCallback() {
        super.disconnectedCallback();
    }
    onResize() {
        if(this.timeOutResize)
            clearTimeout(this.timeOutResize);
        this.timeOutResize = setTimeout(() => {
            this.setSize();
        }, 500);
    }
    // Not used any more
    toggleHeader() {
        // The header is displayed for a maximum of 10 seconds
        this.displayHeader = !this.displayHeader;
        if(this.displayHeader) {
            this.StartedDisplayHeader = true;
            setTimeout(() => {
                this.StartedDisplayHeader = false;
            }, 10000);
        }
        else {
            this.StartedDisplayHeader = false;
        }
    }
    minimize() {
        if(!this.ingameUi.extern && !this.preventMinimize) {
            this.ingameUi.ToggleMinimized(true);
        }
    }
    toggleShowWidth() {
        this.showWidth = !this.showWidth;
        if(this.showWidth)
            this.ingameUi.classList.remove("hideWidth");
        else
            this.ingameUi.classList.add("hideWidth");
    }
    toggleStandby() {
        this.standby = !this.standby;
        diffAndSetAttribute(this.getChildById("standby"), "state", this.standby ? "on" : "off");
        diffAndSetAttribute(this.getChildById("MainframeGtn"), "standby", this.standby ? "on" : "off");
    }
    setSize() {
        // GTN resizing
        // Not super precise but enough
        if(this.preventResize)
            return;
        if(this.mainframeGtn && this.ingameUiheader) {
            let newHeight = (this.ingameUi.getBoundingClientRect().height - this.ingameUiheader.getBoundingClientRect().height) / 1.01;
            let newWidth = Math.round(newHeight/1.1815);
            newHeight = Math.round(newHeight);
            if(this.debugPanel)
            {
                console.log("panel resize: Width:" + newWidth + " - Height: " + newHeight);
                let standby = this.getChildById("standby");
                diffAndSetHTML(standby, "Width:" + newWidth + " - Height: " + newHeight);

            }
            diffAndSetAttribute(this.mainframeGtn, "style", "height: " + newHeight + "px; width: " + newWidth + "px;");
            // Resize counter used to redraw some svg image elements after a resize (bug in MSFS)
            // Seems to be fixed so we comment the next line (occurs only with the debugger)
            this.resizeCounter++;
            SimVar.SetSimVarValue("L:PANEL_GTN750_RESIZE_COUNTER", "number", this.resizeCounter);
            this.preventResize = true;
            setTimeout(() => {
                this.preventResize = false;
            },2000);
        }
    }
    // We override that in order to start the panel in aircraft that do not have a specific avionics circuit
    // The instrument power on is based on the main bus voltage
    isElectricityAvailable() {
        if (this.electricalLogic) {
            return this.electricalLogic.getValue() != 0;
        }
        return true;
        return SimVar.GetSimVarValue("ELECTRICAL MAIN BUS VOLTAGE", "Volts") > 5;
//        return SimVar.GetSimVarValue("CIRCUIT AVIONICS ON", "Bool");
    }
}

// Monkey Patch to bypass loading instruments
// Note this is a hack which could have unknown side effects. There is code in the baseinstrument base class which checks all
// instruments are registered before proceeding. Because we are loading this within an ingamepanel and are not loading this as an
// instrument, this instument is not loaded so we force loading through BaseInstrument.allInstrumentsLoaded
//registerInstrument("ingamepanel-custom", IngamePanelCustomPanel);
BaseInstrument.allInstrumentsLoaded = true;
window.customElements.define("ingamepanel-custom", IngamePanelCustomPanel);
checkAutoload();