//PM Modif: Many modifications. Check all the file
class SvgWaypointElement extends SvgMapElement {
    constructor(source) {
        super();
        this.textOffsetRatio = 0.25;
        this.showText = true;
        this.minimize = false;
        this._alpha = NaN;
        this._textWidth = NaN;
        this._textHeight = NaN;
        this.needRepaint = false;
        this._lastX = 0;
        this._lastY = 0;
        this._lastMinimize = false;
        this._lastIsActiveWaypoint = false;
        this._lastMinimizeVOR = null;
        this.source = source;
        this.selected = false;
        this.resizeCounter = 0;
        this._tforcerefresh = 0;
        this.iconSize = 100;
    }
    get ident() {
        if (this._ident) {
            return this._ident;
        }
        if (this.source) {
            return this.source.ident;
        }
    }
    set ident(v) {
        this._ident = v;
    }
    get icao() {
        if (this._icao) {
            return this._icao;
        }
        if (this.source) {
            return this.source.icao;
        }
    }
    get icaoNoSpace() {
        if (this.source instanceof WayPoint) {
            return this.source.icaoNoSpace;
        }
        if (!this._icaoNoSpace) {
            if (this.icao) {
                this._icaoNoSpace = this.icao;
                while (this._icaoNoSpace.indexOf(" ") != -1) {
                    this._icaoNoSpace = this._icaoNoSpace.replace(" ", "_");
                }
            }
        }
        if (this._icaoNoSpace) {
            return this._icaoNoSpace;
        }
    }
    set icao(v) {
        this._icao = v;
        this._icaoNoSpace = this._icao;
        while (this._icaoNoSpace.indexOf(" ") != -1) {
            this._icaoNoSpace.replace(" ", "_");
        }
    }
    get coordinates() {
        if (this._coordinates) {
            return this._coordinates;
        }
        if (this.source && this.source.coordinates) {
            return this.source.coordinates;
        }
    }
    set coordinates(v) {
        this._coordinates = v;
    }
    get bearing() {
        if (this._bearing) {
            return this._bearing;
        }
        if (this.source) {
            return this.source.bearing;
        }
    }
    set bearing(v) {
        this._bearing = v;
    }
    get distance() {
        if (this._distance) {
            return this._distance;
        }
        if (this.source) {
            return this.source.distance;
        }
    }
    set distance(v) {
        this._distance = v;
    }
    imageFileName() {
        if (this.source) {
            return this.source.imageFileName();
        }
    }
    isMinized(map) {
        return false;
    }
    createDraw(map) {
        let fontSize = map.config.waypointLabelFontSize / map.overdrawFactor;
        let text = this.ident;
        let c = document.createElement("canvas");
        let ctx = c.getContext("2d");
        ctx.font = fontSize + "px " + map.config.waypointLabelFontFamily;
        this._textWidth = ctx.measureText(text).width;
        this._textHeight = fontSize * 1.33;
        let isActiveWaypoint = false;
        if (map.instrument && map.instrument.flightPlanManager) {
            let ident = map.instrument.flightPlanManager.getActiveWaypointIdent();
            isActiveWaypoint = this.source.ident === ident;
        }
        this._refreshLabel(map, isActiveWaypoint);
        this._image = document.createElementNS(Avionics.SVG.NS, "image");
        this._image.id = this.id(map);
        this._image.classList.add(this.class() + "-icon");
        diffAndSetAttribute(this._image, "hasTextBox", "true");
        diffAndSetAttribute(this._image, "width", "100%");
        diffAndSetAttribute(this._image, "height", "100%");
        this._image.setAttributeNS("http://www.w3.org/1999/xlink", "href", map.config.imagesDir + this.imageFileName());
        this._lastIsActiveWaypoint = isActiveWaypoint;
        this.iconSize = this instanceof SvgNearestVORElement2 ? 400 : map.config.waypointIconSize;
        diffAndSetAttribute(this._image, "width", fastToFixed(this.iconSize / map.overdrawFactor, 0));
        diffAndSetAttribute(this._image, "height", fastToFixed(this.iconSize / map.overdrawFactor, 0));
        this._lastMinimize = undefined;
        return this._image;
    }
    _refreshLabel(map, isActiveWaypoint, clear) {
        if(this instanceof SvgNearestVORElement2)
            return;
        let labelId = this.id(map) + "-text-" + map.index;
        let label = document.getElementById(labelId);
        if (label instanceof SVGForeignObjectElement) {
            this._label = label;
            this.needRepaint = true;
        }
        let fontSize = map.config.waypointLabelFontSize / map.overdrawFactor;
        let text = this.ident;
        let canvas;
        if (!this._label) {
            this._label = document.createElementNS("http://www.w3.org/2000/svg", "foreignObject");
            this._label.id = labelId;
            let width = this._textWidth + map.config.waypointLabelBackgroundPaddingLeft / map.overdrawFactor + map.config.waypointLabelBackgroundPaddingRight / map.overdrawFactor;
            width *= 1.20;  // We set some margin to avoid text size issues
//            let height = this._textHeight + map.config.waypointLabelBackgroundPaddingTop / map.overdrawFactor + map.config.waypointLabelBackgroundPaddingBottom / map.overdrawFactor;
            let height = this._textHeight;
            height *= 2;  // We set some margin to avoid text size issues especially in VR and big toolbar panel size
            diffAndSetAttribute(this._label, "width", fastToFixed(width, 0));
            diffAndSetAttribute(this._label, "height", fastToFixed(height, 0));
            canvas = document.createElement("canvas");
            diffAndSetAttribute(canvas, "width", fastToFixed(width, 0));
            diffAndSetAttribute(canvas, "height", fastToFixed(height, 0));
            this._label.appendChild(canvas);
            map.textLayer.appendChild(this._label);
        }
        else {
            canvas = this._label.querySelector("canvas");
        }
        if (!canvas) {
            return;
        }
        let context = canvas.getContext("2d");
        if(clear)
            context.clearRect(0, 0, canvas.width, canvas.height);
        if (!isFinite(this._textWidth) || clear)
            this._textWidth = context.measureText(text).width;
        if (!isFinite(this._textHeight))
            this._textHeight = fontSize * 1.33;

        if (this.isPartOfFP && map.config.waypointLabelUseBackground || this.selected) {
            context.fillStyle = isActiveWaypoint ? map.config.waypointActiveLabelBackgroundColor : map.config.waypointLabelBackgroundColor;
            if(this.selected)
                context.fillStyle = isActiveWaypoint ? map.config.waypointSelectedActiveLabelBackgroundColor : map.config.waypointSelectedLabelBackgroundColor;
//            context.fillRect(0, 0, this._textWidth + map.config.waypointLabelBackgroundPaddingLeft / map.overdrawFactor + map.config.waypointLabelBackgroundPaddingRight / map.overdrawFactor, this._textHeight + map.config.waypointLabelBackgroundPaddingTop / map.overdrawFactor + map.config.waypointLabelBackgroundPaddingBottom / map.overdrawFactor);
            context.fillRect(0, 0, this._textWidth + map.config.waypointLabelBackgroundPaddingLeft / map.overdrawFactor + map.config.waypointLabelBackgroundPaddingRight / map.overdrawFactor, this._textHeight);
            context.lineWidth = map.config.waypointLabelBackgroundStrokeWidth;
            context.strokeStyle = isActiveWaypoint ? map.config.waypointActiveLabelBackgroundStrokeColor : map.config.waypointLabelBackgroundStrokeColor;
            if(this.selected)
                context.strokeStyle = isActiveWaypoint ? map.config.waypointSelectedActiveLabelBackgroundStrokeColor : map.config.waypointSelectedLabelBackgroundStrokeColor;
//            context.strokeRect(0, 0, this._textWidth + map.config.waypointLabelBackgroundPaddingLeft / map.overdrawFactor + map.config.waypointLabelBackgroundPaddingRight / map.overdrawFactor, this._textHeight + map.config.waypointLabelBackgroundPaddingTop / map.overdrawFactor + map.config.waypointLabelBackgroundPaddingBottom / map.overdrawFactor);
            context.strokeRect(0, 0, this._textWidth + map.config.waypointLabelBackgroundPaddingLeft / map.overdrawFactor + map.config.waypointLabelBackgroundPaddingRight / map.overdrawFactor, this._textHeight);
        }
        context.fillStyle = isActiveWaypoint ? map.config.waypointActiveLabelColor : map.config.waypointLabelColor;
        if(this.selected)
            context.fillStyle = isActiveWaypoint ? map.config.waypointSelectedActiveLabelColor : map.config.waypointSelectedLabelColor;
        context.font = fontSize + "px " + map.config.waypointLabelFontFamily;
        if(!this.isPartOfFP && !this.selected) {
            context.fillStyle = map.config.waypointLabelBackgroundColor;
            context.lineWidth = 2;
            context.strokeStyle = map.config.waypointLabelBackgroundStrokeColor;
            context.textBaseline = "bottom";
//            context.strokeText(text, map.config.waypointLabelBackgroundPaddingLeft / map.overdrawFactor, this._textHeight + map.config.waypointLabelBackgroundPaddingTop / map.overdrawFactor);
            context.strokeText(text, map.config.waypointLabelBackgroundPaddingLeft / map.overdrawFactor, this._textHeight);
        }
//        context.fillText(text, map.config.waypointLabelBackgroundPaddingLeft / map.overdrawFactor, this._textHeight + map.config.waypointLabelBackgroundPaddingTop / map.overdrawFactor);
        context.textBaseline = "bottom";
        context.fillText(text, map.config.waypointLabelBackgroundPaddingLeft / map.overdrawFactor, this._textHeight);
    }
    updateDraw(map) {
        if (this.coordinates) {
            map.coordinatesToXYToRef(this.coordinates, this);
        }
        else if (isFinite(this.source.latitudeFP) && isFinite(this.source.longitudeFP)) {
            map.coordinatesToXYToRef(new LatLongAlt(this.source.latitudeFP, this.source.longitudeFP), this);
        }
        else {
            let pos = map.bearingDistanceToXY(this.bearing, this.distance);
            this.x = pos.x;
            this.y = pos.y;
        }
// PM Modif: No correction in get active waypoint index so the active waypoint is correctly displayed
        let wp = FlightPlanManager.DEBUG_INSTANCE.getActiveWaypoint(false);
        if (this.source && this.source.instrument && this.source.instrument.flightPlanManager) {
            wp = this.source.instrument.flightPlanManager.getActiveWaypoint(false);
        }
// PM Modif: End No correction in get active waypoint index so the active waypoint is correctly displayed

        let isActiveWaypoint = this.source === wp || (wp && wp.icao.split("_")[0] === this.source.icao.split("_")[0] && wp.ident === this.source.ident);
//PM Modif: Bug resize
        let forceRefresh = false;
        if(this.source.instrument.isPanel || this.source.instrument.instrumentIdentifier === "VFRMap") {
            let panelResizeCounter = SimVar.GetSimVarValue("L:PANEL_GTN750_RESIZE_COUNTER", "number");
            if(this.resizeCounter != panelResizeCounter)
                forceRefresh = true;
            this.resizeCounter = panelResizeCounter;
            this._tforcerefresh++;
            if(this._tforcerefresh > 1000) {
                forceRefresh = true;
                this._tforcerefresh = 0;
            }
        }
        if (isActiveWaypoint != this._lastIsActiveWaypoint || forceRefresh) {
//PM Modif: End Bug resize
            this._refreshLabel(map, isActiveWaypoint, true);
            if (this._image) {
//PM Modif: Map waypoint image correct also for active WP
                this._image.setAttributeNS("http://www.w3.org/1999/xlink", "href", map.config.imagesDir + this.imageFileName());
//PM Modif: End Map waypoint image correct also for active WP
            }
            this._lastIsActiveWaypoint = isActiveWaypoint;
        }
        if(!this.selected && this.wasSelected) {
            this._refreshLabel(map, isActiveWaypoint, true);
            this.wasSelected = false;
        }
        if(this.selected && !this.wasSelected) {
            this._refreshLabel(map, isActiveWaypoint, true);
            this.wasSelected = true;
        }
        if(!this.isPartOfFP && this.wasPartOfFP) {
            this._refreshLabel(map, isActiveWaypoint, true);
            this.wasPartOfFP = false;
        }
        // For now we always refresh flight plan label
        if(this.isPartOfFP) {
            this._refreshLabel(map, isActiveWaypoint, true);
            this.wasPartOfFP = true;
        }
        if (isFinite(this.x) && isFinite(this.y)) {
//PM Modif: No Minimize for GTN750
//            this.minimize = this.isMinized(map);
//PM Modif: End No Minimize
            if (this._image && this._lastMinimize != this.minimize) {
                if (this.minimize) {
                    diffAndSetAttribute(this._image, "width", fastToFixed(this.iconSize / map.overdrawFactor * 0.5, 0));
                    diffAndSetAttribute(this._image, "height", fastToFixed(this.iconSize / map.overdrawFactor * 0.5, 0));
                }
                else {
                    diffAndSetAttribute(this._image, "width", fastToFixed(this.iconSize / map.overdrawFactor, 0));
                    diffAndSetAttribute(this._image, "height", fastToFixed(this.iconSize / map.overdrawFactor, 0));
                }
                this._lastMinimize = this.minimize;
                this.needRepaint = true;
            }
            if (this.needRepaint || Math.abs(this._lastX - this.x) > 0.1 || Math.abs(this._lastY - this.y) > 0.1) {
                this._lastX = this.x;
                this._lastY = this.y;
                let x = (this.x - this.iconSize / map.overdrawFactor * 0.5 * (this.minimize || this.minimizeVOR ? 0.5 : 1));
                let y = (this.y - this.iconSize / map.overdrawFactor * 0.5 * (this.minimize || this.minimizeVOR ? 0.5 : 1));
                diffAndSetAttribute(this.svgElement, "x", x + "");
                diffAndSetAttribute(this.svgElement, "y", y + "");
                if (this.source instanceof AirportInfo) {
                    let a = this.source.longestRunwayDirection;
//PM Modif: Get ourselves the longuest runway direction if not found from FS9 variable
                    if (isNaN(a) && this.source.runways.length) {
                        a = this.source.runways[0].direction;
                        let rmaxlength = this.source.runways[0].length;
                        for(let i=1; i<this.source.runways.length; i++){
                            if(this.source.runways[i].length > rmaxlength) {
                                rmaxlength = this.source.runways[i].length;
                                a = this.source.runways[i].direction;
                            }
                        }
                    }
//PM Modif: End Get ourselves the longuest runway direction if not found from FS9 variable
                    if (isFinite(a)) {
                        this._alpha = a - 45;
                    }
                }
                if(this instanceof SvgNearestVORElement2)
                    this._alpha = -this.source.magneticVariation;
                if (isFinite(this._alpha)) {
//PM Modif: Correct angle for track up
                    if (map.rotationMode != EMapRotationMode.NorthUp) {
                        this._alpha -= map.mapUpDirection;
                    }
//PM Modif: End Correct angle for track up
                    diffAndSetAttribute(this.svgElement, "transform", "rotate(" + fastToFixed(this._alpha, 0) + " " + fastToFixed(this.x, 0) + " " + fastToFixed(this.y, 0) + ")");
                }
                if(this instanceof SvgNearestVORElement2) {
                    this.minimizeVOR = map._ftWidth > 400000;
                    if (this._image) {
                        if (this.minimizeVOR) {
                            diffAndSetAttribute(this._image, "width", fastToFixed(this.iconSize / map.overdrawFactor * 0.5, 0));
                            diffAndSetAttribute(this._image, "height", fastToFixed(this.iconSize / map.overdrawFactor * 0.5, 0));
                        }
                        else {
                            diffAndSetAttribute(this._image, "width", fastToFixed(this.iconSize / map.overdrawFactor, 0));
                            diffAndSetAttribute(this._image, "height", fastToFixed(this.iconSize / map.overdrawFactor, 0));
                        }
                        this._lastMinimizeVOR = this.minimizeVOR;
                        this.needRepaint = true;
                    }
                }
                else {
                    if (!this._label) {
                        let labelId = this.id(map) + "-text-" + map.index;
                        let label = document.getElementById(labelId);
                        if (label instanceof SVGForeignObjectElement) {
                            let c = document.createElement("canvas");
                            let ctx = c.getContext("2d");
                            let fontSize = map.config.waypointLabelFontSize / map.overdrawFactor;
                            let text = this.ident;
                            ctx.font = fontSize + "px " + map.config.waypointLabelFontFamily;
                            this._textWidth = ctx.measureText(text).width;
                            this._textHeight = fontSize * 1.33;
                            this._label = label;
                            this.needRepaint = true;
                        }
                    }
                }
                if (this._label) {
                    if (!isFinite(this._textWidth)) {
                        let c = document.createElement("canvas");
                        let ctx = c.getContext("2d");
                        let fontSize = map.config.waypointLabelFontSize / map.overdrawFactor;
                        let text = this.ident;
                        ctx.font = fontSize + "px " + map.config.waypointLabelFontFamily;
                        this._textWidth = ctx.measureText(text).width;
                        this._textHeight = fontSize * 1.33;
                    }
                    if (!isFinite(this._textHeight)) {
                        let fontSize = map.config.waypointLabelFontSize / map.overdrawFactor;
                        this._textHeight = fontSize * 0.675;
                    }
                    let textX = (x + this.iconSize / map.overdrawFactor * 0.5 - this._textWidth * 0.5 + map.config.waypointLabelDistanceX / map.overdrawFactor);
                    let textY = y + map.config.waypointLabelDistance / map.overdrawFactor;
                    diffAndSetAttribute(this._label, "x", textX + "");
                    diffAndSetAttribute(this._label, "y", textY + "");
                    this.needRepaint = false;
                }
                else {
                    this.needRepaint = true;
                }
            }
        }
    }
}
