//PM Modif: Many modifs, check all the file
class SvgConstraintElement extends SvgMapElement {
    constructor(source) {
        super();
        this.textOffsetRatio = 3;
        this.showText = true;
        this.minimize = false;
        this._textWidth = NaN;
        this._textHeight = NaN;
        this.needRepaint = false;
        this._lastX = 0;
        this._lastY = 0;
        this._lastMinimize = false;
        this._lastIsActiveWaypoint = false;
        this.source = source;
        this.selected = false;
        this._id = SvgConstraintElement._ID++;
        this.sortIndex = 4; // higher priority on other text elements
    }
    get coordinates() {
        if (this._coordinates) {
            return this._coordinates;
        }
        if (this.source && this.source.infos.coordinates) {
            return this.source.infos.coordinates;
        }
    }
    set coordinates(v) {
        this._coordinates = v;
    }
    id(map) {
        return "constraint-" + this.source.icaoNoSpace + "-map-" + map.index;
        ;
    }
    imageFileName() {
        return "ICON_CSTR_MAGENTA.svg";
    }
    createDraw(map) {
        let fontSize = map.config.waypointLabelFontSize / map.overdrawFactor * 0.9;
        let text = "CSTR";
        let speedText = "";
        if (this.source) {
            let altitude = this.source.legAltitudeDescription < 10 && this.source.legAltitude1 ? this.source.legAltitude1 : this.source.altitudeinFP;
            text = fastToFixed((altitude / 10), 0) + "0";
            if (this.source.speedConstraint > 10)
                speedText = fastToFixed(this.source.speedConstraint, 0) + "KT";
        }
        if (this.source.speedConstraint > 10) {
            speedText = fastToFixed(this.source.speedConstraint, 0) + "KT";
        }
        let ident;
        let activeWaypoint = FlightPlanManager.DEBUG_INSTANCE.getActiveWaypoint(true);
        if (activeWaypoint) {
            ident = activeWaypoint.ident;
        }
        let isActiveWaypoint = this.source.ident === ident;
        let c = document.createElement("canvas");
        let ctx = c.getContext("2d");
        ctx.font = fontSize + "px " + map.config.waypointLabelFontFamily;
        this._textWidth = Math.max(ctx.measureText(text).width, ctx.measureText(speedText).width);
        this._textHeight = fontSize * 0.675;
        this._label = undefined;
        this.needRepaint = true;
        this._refreshLabel(map);
        this.svgElement = document.createElementNS(Avionics.SVG.NS, "image");
        this.svgElement.id = this.id(map);
        this.svgElement.classList.add("constraint-icon");
        diffAndSetAttribute(this.svgElement, "hasTextBox", "true");
        // Constraint icon not used here
        //this.svgElement.setAttributeNS("http://www.w3.org/1999/xlink", "href", map.config.imagesDir + this.imageFileName());
        diffAndSetAttribute(this.svgElement, "width", fastToFixed(map.config.waypointIconSize / map.overdrawFactor * 1.3, 0));
        diffAndSetAttribute(this.svgElement, "height", fastToFixed(map.config.waypointIconSize / map.overdrawFactor * 1.3, 0));
        this._lastIsActiveWaypoint = isActiveWaypoint;
        return this.svgElement;
    }
    // Refresh label rebuilt and called from update
    // Because the constraint elment are not refreshed with new value otherwise
    _refreshLabel(map, isActiveWaypoint) {
        this._label = undefined;
        this.needRepaint = true;
        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 * 0.9;
        let altitude1 = "";
        let altitude2 = "";
        let speedText = "";
        let ident = "";
        let altState = "";
        let isWTTWaypoint = this.source && this.source.WTData && this.source.WTData.WTSegmentIndex >= 0;
        if (this.source) {
            let altitude = this.source.legAltitudeDescription < 10 && this.source.legAltitude1 ? this.source.legAltitude1 : this.source.altitudeinFP;
            altitude1 = fastToFixed((altitude / 10), 0) + "0";
            if(isWTTWaypoint && altitude && this.source.legAltitudeDescription < 10) {
                if(this.source.legAltitudeDescription == 1)
                    altState = "At";
                else if(this.source.legAltitudeDescription == 2)
                    altState = "Above";
                else if(this.source.legAltitudeDescription == 3)
                    altState = "Below";
                else if(this.source.legAltitudeDescription == 4) {
                    altitude2 = fastToFixed((this.source.legAltitude2 / 10), 0) + "0";
                    altState = "Between";
                }
            }
            ident = this.source.ident;
            if (this.source.speedConstraint > 10)
                speedText = fastToFixed(this.source.speedConstraint, 0) + "KT";
        }
        let canvas;
        let labelCreated = false;
        if (!this._label) {
            labelCreated = true;
            canvas = document.createElement("canvas");
            this._label = document.createElementNS("http://www.w3.org/2000/svg", "foreignObject");
            this._label.id = labelId;
        }
        else
            canvas = this._label.querySelector("canvas");
        if (!canvas)
            return;
        let context = canvas.getContext("2d");
        context.clearRect(0, 0, canvas.width, canvas.height);
        this._textWidth = Math.max(context.measureText(ident).width, context.measureText(altitude1).width, context.measureText(altitude2).width, context.measureText(speedText).width);
        this._textHeight = fontSize * 0.675;
        let sepSize = this._textHeight * 0.8;
        let width = this._textWidth + map.config.waypointLabelBackgroundPaddingLeft / map.overdrawFactor + map.config.waypointLabelBackgroundPaddingRight;
        let height = ident.length ? this._textHeight : 0;
        if(altitude1.length) {
            height += (height > 0 ? sepSize : 0) + this._textHeight;
            if(isWTTWaypoint && altitude2.length)
                height += this._textHeight + (sepSize/3);
        }
        if(speedText.length)
            height += (height > 0 ? sepSize : 0) + this._textHeight;
        height += 5 + (map.config.waypointLabelBackgroundPaddingTop + map.config.waypointLabelBackgroundPaddingBottom) / map.overdrawFactor;
        diffAndSetAttribute(this._label, "width", fastToFixed(width, 0));
        diffAndSetAttribute(this._label, "height", fastToFixed(height, 0));
        this.labelWidth = width;
        this.labelHeight = height;
        diffAndSetAttribute(canvas, "width", fastToFixed(width, 0));
        diffAndSetAttribute(canvas, "height", fastToFixed(height, 0));
        if(labelCreated) {
            this._label.appendChild(canvas);
            map.textLayer.appendChild(this._label);
        }
        if (map.config.waypointLabelUseBackground || this.selected) {
            context.fillStyle = "black";
            context.fillRect(0, 0, width, height);
        }
        context.font = fontSize + "px " + map.config.waypointLabelFontFamily;
        context.fillStyle = isActiveWaypoint ? "magenta" : "#D0D0D0";
        if(this.selected)
            context.fillStyle = "yellow";
        let heightOffset = map.config.waypointLabelBackgroundPaddingTop;
        if(ident.length) {
            context.fillText(ident, map.config.waypointLabelBackgroundPaddingLeft / map.overdrawFactor, this._textHeight + heightOffset);
            heightOffset += this._textHeight + sepSize;
        }
        context.fillStyle = "white";
        if(altitude1.length) {
            if(altState == "Below" || altState == "At" || altState == "Between") {
                context.save();
                context.fillStyle = "#A0A0A0";
                this.underlineText(context, altitude1, map.config.waypointLabelBackgroundPaddingLeft / map.overdrawFactor, this._textHeight + heightOffset, 3, -fontSize + 3);
                context.restore();
            }
            context.fillText(altitude1, map.config.waypointLabelBackgroundPaddingLeft / map.overdrawFactor, this._textHeight + heightOffset);
            if(isWTTWaypoint && altitude2.length) {
                heightOffset += this._textHeight + (sepSize/3);
                context.fillText(altitude2, map.config.waypointLabelBackgroundPaddingLeft / map.overdrawFactor, this._textHeight + heightOffset);
            }
            if(altState == "Above" || altState == "At" || altState == "Between") {
                context.save();
                context.fillStyle = "#A0A0A0";
                this.underlineText(context, altitude1, map.config.waypointLabelBackgroundPaddingLeft / map.overdrawFactor, this._textHeight + heightOffset, 3, 5);
                context.restore();
            }
            heightOffset += this._textHeight + sepSize;
        }
        context.fillStyle = "lightgreen";
        if(speedText.length) {
            context.fillText(speedText, map.config.waypointLabelBackgroundPaddingLeft / map.overdrawFactor, this._textHeight + heightOffset);
            heightOffset += this._textHeight + sepSize;
        }
    }

    underlineText(ctx, text, x, y, lineWidth, offset) {
        let metrics = ctx.measureText(text);
        ctx.save();
        ctx.beginPath();
        ctx.strokeStyle = ctx.fillStyle;
        ctx.lineWidth = lineWidth;
        ctx.moveTo(x, y + offset);
        ctx.lineTo(x + metrics.width, y + offset);
        ctx.stroke();
        ctx.restore();
    }

    updateDraw(map) {
        if (this.coordinates) {
            map.coordinatesToXYToRef(this.coordinates, this);
        }
// 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

        //PM Modif: Check also ident
        let isActiveWaypoint = this.source === wp || (wp && wp.icao === this.source.icao) || (wp && wp.ident === this.source.ident);
        //PM Modif: End Check also ident
        if (isActiveWaypoint != this._lastIsActiveWaypoint) {
            this._refreshLabel(map, isActiveWaypoint);
            this._lastIsActiveWaypoint = isActiveWaypoint;
        }
        if(!this.selected && this.wasSelected) {
            this._refreshLabel(map, isActiveWaypoint);
            this.wasSelected = false;
        }
        if(this.selected && !this.wasSelected) {
            this._refreshLabel(map, isActiveWaypoint);
            this.wasSelected = true;
        }
        if (isFinite(this.x) && isFinite(this.y)) {
            if (this.svgElement && this._lastMinimize !== this.minimize) {
                if (this.minimize) {
                    diffAndSetAttribute(this.svgElement, "width", fastToFixed(map.config.waypointIconSize / map.overdrawFactor * 1.3 * 0.5, 0));
                    diffAndSetAttribute(this.svgElement, "height", fastToFixed(map.config.waypointIconSize / map.overdrawFactor * 1.3 * 0.5, 0));
                }
                else {
                    diffAndSetAttribute(this.svgElement, "width", fastToFixed(map.config.waypointIconSize / map.overdrawFactor * 1.3, 0));
                    diffAndSetAttribute(this.svgElement, "height", fastToFixed(map.config.waypointIconSize / map.overdrawFactor * 1.3, 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 - map.config.waypointIconSize / map.overdrawFactor * 1.1 * 0.5 * (this.minimize ? 0.5 : 1));
//                let y = (this.y - map.config.waypointIconSize / map.overdrawFactor * 1.7 * 0.5 * (this.minimize ? 0.5 : 1));
                let y = (this.y - map.config.waypointIconSize / map.overdrawFactor * 0.25 * (this.minimize? 0.5 : 1));
                diffAndSetAttribute(this.svgElement, "x", x + "");
                diffAndSetAttribute(this.svgElement, "y", y + "");
                this._refreshLabel(map, isActiveWaypoint);
                if (this._label) {
                    let textX = (x + map.config.waypointIconSize / map.overdrawFactor * 0.5 - this._textWidth * 0.5 + map.config.waypointLabelDistanceX / map.overdrawFactor);
                    let textY = y - this.labelHeight + map.config.waypointLabelDistance / map.overdrawFactor / 5;
                    diffAndSetAttribute(this._label, "x", textX + "");
                    diffAndSetAttribute(this._label, "y", textY + "");
                    this.needRepaint = false;
                }
                else {
                    this.needRepaint = true;
                }
            }
        }
    }
}
SvgConstraintElement._ID = 0;
class SvgTopOfXElement extends SvgMapElement {
    constructor(name, imageName) {
        super();
        this.imageName = imageName;
        this.heading = 0;
        this._lastX = 0;
        this._lastY = 0;
        this._lastFileName = "";
        this.name = name;
        if (!this.name) {
            this.name = fastToFixed((Math.random() * 10), 0).padStart(10, "0");
        }
    }
    id(map) {
        return this.name + "-map-" + map.index;
        ;
    }
    imageFileName() {
        return this.imageName + ".svg";
    }
    createDraw(map) {
        let container = document.createElementNS(Avionics.SVG.NS, "image");
        container.id = this.id(map);
        container.classList.add("map-city-icon");
        diffAndSetAttribute(container, "width", fastToFixed(map.config.waypointIconSize / map.overdrawFactor * 2, 0));
        diffAndSetAttribute(container, "height", fastToFixed(map.config.waypointIconSize / map.overdrawFactor * 2, 0));
        container.setAttributeNS("http://www.w3.org/1999/xlink", "href", map.config.imagesDir + this.imageFileName());
        return container;
    }
    updateDraw(map) {
        map.latLongToXYToRef(this.lat, this.long, this);
        if (isFinite(this.x) && isFinite(this.y)) {
            let fileName = this.imageFileName();
            if (fileName !== this._lastFileName) {
                this.svgElement.setAttributeNS("http://www.w3.org/1999/xlink", "href", map.config.imagesDir + fileName);
                this._lastFileName = fileName;
            }
            if (Math.abs(this.x - this._lastX) > 0.1 || Math.abs(this.y - this._lastY) > 0.1) {
                diffAndSetAttribute(this.svgElement, "x", fastToFixed((this.x - map.config.waypointIconSize / map.overdrawFactor), 1));
                diffAndSetAttribute(this.svgElement, "y", fastToFixed((this.y - map.config.waypointIconSize / map.overdrawFactor), 1));
                let angle = this.heading;
                if (map.rotationMode != EMapRotationMode.NorthUp) {
                    angle -= map.mapUpDirection;
                }
                diffAndSetAttribute(this.svgElement, "transform", "rotate(" + fastToFixed(angle, 0) + " " + fastToFixed(this.x, 0) + " " + fastToFixed(this.y, 0) + ")");
                this._lastX = this.x;
                this._lastY = this.y;
            }
        }
    }
}
