class NearestAirspacesLoader {
    constructor(_instrument) {
        this.lla = new LatLongAlt;
        this.nearestAirspaces = [];
        this._updating = false;
        this.instrument = _instrument;
    }
    update() {
        if (!this._updating && (this._lastlla == undefined || Math.abs(this._lastlla.lat - this.lla.lat) > 0.25 || Math.abs(this._lastlla.long - this.lla.long) > 0.25)) {
            this._updating = true;
            Coherent.call("SET_LOAD_LATLON", this.lla.lat, this.lla.long).then(() => {
                Coherent.call("GET_NEAREST_AIRSPACES").then((airspaces) => {
                    for (let i = 0; i < airspaces.length; i++) {
                        let airspaceData = airspaces[i];
                        if (airspaceData.type !== 1) {
                            let name = "airspace-";
                            name += airspaceData.type;
                            if (airspaceData.segments.length > 2) {
                                name += fastToFixed(airspaceData.segments[0].lat, 5);
                                name += fastToFixed(airspaceData.segments[1].long, 5);
                            }
                            if (!this.nearestAirspaces.find(a => { return a.name === name; })) {
                                let nearestAirspace = new NearestAirspace();
                                nearestAirspace.type = airspaces[i].type;
                                nearestAirspace.name = name;
                                nearestAirspace.ident = nearestAirspace.name;
                                nearestAirspace.segments = airspaces[i].segments;
                                this.nearestAirspaces.push(nearestAirspace);
                                if (this.onNewAirspaceAddedCallback) {
                                    this.onNewAirspaceAddedCallback(nearestAirspace);
                                }
                            }
                        }
                    }
                    this._updating = false;
                    this._lastlla = this.lla.toLatLong();
                    if (this.nearestAirspaces.length > 50) {
                        this.nearestAirspaces.splice(0, this.nearestAirspaces.length - 50);
                    }
                });
            });
        }
    }
}
// PM Modif changed class name for WT compatibility
class StockFacilityLoader {
    constructor(_instrument) {
        this.pendingRequests = [];
        this.loadingFacilities = [];
        this.loadedWaypoints = [];
        this.loadedFacilityDatas = [];
        this.loadedAirwayDatas = new Map();
        this._isRegistered = false;
        this._isCompletelyRegistered = false;
        this._maxSimultaneousCoherentCalls = 20;
        this._pendingGetFacilityCoherentCall = [];
        this.instrument = _instrument;
        this.registerListener();
    }
    registerListener() {
        if (this._isRegistered) {
            return;
        }
        this._isRegistered = true;
        RegisterViewListener("JS_LISTENER_FACILITY", () => {
            console.log("JS_LISTENER_FACILITY registered.");
            Coherent.on("SendAirport", (data) => {
                this.addFacility(data);
            });
            Coherent.on("SendIntersection", (data) => {
                this.addFacility(data);
            });
            Coherent.on("SendVor", (data) => {
                this.addFacility(data);
            });
            Coherent.on("SendNdb", (data) => {
                this.addFacility(data);
            });
            this._isCompletelyRegistered = true;
        }, true);
    }
    update() {
        if (this._pendingGetFacilityCoherentCall.length > 0) {
            for (let i = 0; i < 5; i++) {
                if (this.loadingFacilities.length < this._maxSimultaneousCoherentCalls) {
                    let coherentCall = this._pendingGetFacilityCoherentCall.splice(0, 1)[0];
                    if (coherentCall) {
                        coherentCall();
                    }
                }
            }
        }
    }
    addFacility(_data) {
        _data.icaoTrimed = _data.icao.trim();
        let isLoaded = this.loadedFacilityDatas.findIndex(f => {
            if (f.icao === _data.icao) {
                if (_data.routes != undefined && f.routes != undefined) {
                    return true;
                }
                if (_data.routes === undefined && f.routes === undefined) {
                    return true;
                }
            }
            return false;
        }) != -1;
        if (!isLoaded) {
            this.loadedFacilityDatas.push(_data);
            while (this.loadedFacilityDatas.length > 1000) {
                this.loadedFacilityDatas.splice(0, 1);
            }
        }
    }
    getFacilityCB(icao, callback) {
        if (this._isCompletelyRegistered && this.loadingFacilities.length < this._maxSimultaneousCoherentCalls) {
            let loadedWaypoint = this.loadedWaypoints.find(wp => {
                return wp.icao === icao;
            });
            if (loadedWaypoint) {
                return callback(loadedWaypoint);
            }
            this.getFacilityDataCB(icao, (data) => {
                let waypoint;
                if (data) {
                    waypoint = new WayPoint(this.instrument);
                    this.loadedWaypoints.push(waypoint);
                    while (this.loadedWaypoints.length > 1000) {
                        this.loadedWaypoints.splice(0, 1);
                    }
                    waypoint.SetFromIFacility(data, () => {
                        return callback(waypoint);
                    });
                }
                else {
                    return callback(undefined);
                }
            });
        }
        else {
            this._pendingGetFacilityCoherentCall.push(this.getFacilityCB.bind(this, icao, callback));
        }
    }
    async waitRegistration() {
        if (!this._isCompletelyRegistered) {
            let waitForCompleteRegistration = () => {
                return new Promise(resolve => {
                    let f = () => {
                        if (this._isCompletelyRegistered) {
                            resolve();
                        }
                        else {
                            this.instrument.requestCall(f);
                        }
                    };
                    f();
                });
            };
            await waitForCompleteRegistration();
        }
    }
    async getFacility(icao) {
        return new Promise(resolve => {
            return this.getFacilityCB(icao, (wp) => {
                resolve(wp);
            });
        });
    }
    getFacilityDataCB(icao, callback) {
        if (this._isCompletelyRegistered) {
            if (!icao) {
                return callback(undefined);
            }
            let typeChar = icao[0];
            if (typeChar === "W") {
                return this.getIntersectionDataCB(icao, callback);
            }
            else if (typeChar === "A") {
                return this.getAirportDataCB(icao, callback);
            }
            else if (typeChar === "V") {
                return this.getVorDataCB(icao, callback);
            }
            else if (typeChar === "N") {
                return this.getNdbDataCB(icao, callback);
            }
            else {
                return callback(undefined);
            }
        }
        else {
            this._pendingGetFacilityCoherentCall.push(this.getFacilityDataCB.bind(this, icao, callback));
        }
    }
    async getFacilityData(icao) {
        return new Promise(resolve => {
            return this.getFacilityDataCB(icao, data => {
                resolve(data);
            });
        });
    }
    async getAirport(icao) {
        await this.waitRegistration();
        let data = await this.getAirportData(icao);
        if (data) {
            let airport = new WayPoint(this.instrument);
            airport.SetFromIFacility(data);
            return airport;
        }
    }
    getAirportDataCB(icao, callback) {
        if (this._isCompletelyRegistered && this.loadingFacilities.length < this._maxSimultaneousCoherentCalls) {
            icao = icao.trim();
            let airport = this.loadedFacilityDatas.find(f => { return f.icaoTrimed === icao && (f.routes === undefined); });
            if (airport) {
                console.log("Airport found in loadedFacilities array.");
                return callback(airport);
            }
            else {
                console.log("Airport not found in loadedFacilities array.");
                console.log(this.loadedFacilityDatas);
            }
            if (icao[0] !== "A") {
                console.warn("Icao mismatch trying to load AIRPORT of invalid icao '" + icao + "'");
            }
            if (this.loadingFacilities.indexOf(icao) === -1) {
                Coherent.call("LOAD_AIRPORT", icao);
                this.loadingFacilities.push(icao);
            }
            let attempts = 0;
            let checkDataLoaded = () => {
                let airport = this.loadedFacilityDatas.find(f => { return f.icaoTrimed === icao && (f.routes === undefined); });
                if (airport) {
                    let n = this.loadingFacilities.indexOf(icao);
                    if (n >= 0) {
                        this.loadingFacilities.splice(n, 1);
                    }
                    callback(airport);
                }
                else {
                    attempts++;
                    if (attempts > 5) {
                        let n = this.loadingFacilities.indexOf(icao);
                        if (n >= 0) {
                            this.loadingFacilities.splice(n, 1);
                        }
                        callback(undefined);
                    }
                    else {
                        this.instrument.requestCall(checkDataLoaded);
                    }
                }
            };
            checkDataLoaded();
        }
        else {
            this.instrument.requestCall(this.getAirportDataCB.bind(this, icao, callback));
        }
    }
    async getAirportData(icao) {
        await this.waitRegistration();
        icao = icao.trim();
        let airport = this.loadedFacilityDatas.find(f => { return f.icaoTrimed === icao && (f.routes === undefined); });
        if (airport) {
            return airport;
        }
        if (icao[0] !== "A") {
            console.warn("Icao mismatch trying to load AIRPORT of invalid icao '" + icao + "'");
        }
        if (this.loadingFacilities.indexOf(icao) === -1) {
            Coherent.call("LOAD_AIRPORT", icao);
            this.loadingFacilities.push(icao);
        }
        return new Promise((resolve) => {
            let attempts = 0;
            let loadedAirportCallback = () => {
                let airport = this.loadedFacilityDatas.find(f => { return f.icaoTrimed === icao && (f.routes === undefined); });
                if (airport) {
                    let n = this.loadingFacilities.indexOf(icao);
                    if (n >= 0) {
                        this.loadingFacilities.splice(n, 1);
                    }
                    resolve(airport);
                }
                else {
                    attempts++;
                    if (attempts > 5) {
                        let n = this.loadingFacilities.indexOf(icao);
                        if (n >= 0) {
                            this.loadingFacilities.splice(n, 1);
                        }
                        resolve(undefined);
                    }
                    else {
                        this.instrument.requestCall(loadedAirportCallback);
                    }
                }
            };
            loadedAirportCallback();
        });
    }
    async getAirports(icaos) {
        await this.waitRegistration();
        let airports = [];
        let datas = await this.getAirportsData(icaos);
        if (datas) {
            for (let i = 0; i < datas.length; i++) {
                let airport = new WayPoint(this.instrument);
                airport.SetFromIFacility(datas[i]);
                airports.push(airport);
            }
        }
        return airports;
    }
    async getAirportsData(icaos) {
        await this.waitRegistration();
        let t0 = performance.now();
        let datas = [];
        for (let i = 0; i < icaos.length; i++) {
            icaos[i] = icaos[i].trim();
        }
        let i = 0;
        while (i < icaos.length) {
            let icao = icaos[i];
            let airport = this.loadedFacilityDatas.find(f => { return f.icaoTrimed === icao && (f.routes === undefined); });
            if (airport) {
                datas.push(airport);
                icaos.splice(i, 1);
            }
            else {
                i++;
            }
        }
        if (icaos.length === 0) {
            return datas;
        }
        for (let i = 0; i < icaos.length; i++) {
            let icao = icaos[i];
            if (icao[0] !== "A") {
                console.warn("Icao mismatch trying to load AIRPORT of invalid icao '" + icao + "'");
            }
        }
        Coherent.call("LOAD_AIRPORTS", icaos, icaos.length);
        return new Promise((resolve) => {
            let attempts = 0;
            let loadedAirportsCallback = () => {
                let i = 0;
                while (i < icaos.length) {
                    let icao = icaos[i];
                    let airport = this.loadedFacilityDatas.find(f => { return f.icaoTrimed === icao && (f.routes === undefined); });
                    if (airport) {
                        datas.push(airport);
                        icaos.splice(i, 1);
                    }
                    else {
                        i++;
                    }
                }
                if (icaos.length === 0) {
                    resolve(datas);
                }
                else {
                    attempts++;
                    if (attempts === 5) {
                        Coherent.call("LOAD_AIRPORTS", icaos, icaos.length);
                    }
                    if (attempts > 10) {
                        console.warn("getAirportsDatas not found for " + icaos.length + " icaos, expect the unexpected.");
                        resolve(datas);
                    }
                    else {
                        this.instrument.requestCall(loadedAirportsCallback);
                    }
                }
            };
            loadedAirportsCallback();
        });
    }
    getIntersectionDataCB(icao, callback) {
        if (icao == "") {
            return null;
        }
        if (this._isCompletelyRegistered && this.loadingFacilities.length < this._maxSimultaneousCoherentCalls) {
            icao = icao.trim();
            let intersection = this.loadedFacilityDatas.find(f => {
                return (f.icaoTrimed === icao) && (f.routes != undefined);
            });
            if (intersection) {
                return callback(intersection);
            }
            if (this.loadingFacilities.indexOf(icao) === -1) {
                Coherent.call("LOAD_INTERSECTION", icao);
                this.loadingFacilities.push(icao);
            }
            let attempts = 0;
            let checkDataLoaded = () => {
                let intersection = this.loadedFacilityDatas.find(f => {
                    return (f.icaoTrimed === icao) && (f.routes != undefined);
                });
                if (intersection) {
                    let n = this.loadingFacilities.indexOf(icao);
                    if (n >= 0) {
                        this.loadingFacilities.splice(n, 1);
                    }
                    callback(intersection);
                }
                else {
                    attempts++;
                    if (attempts > 10) {
                        this.addFacility({
                            icao: icao,
                            icaoTrimed: "",
                            name: "UNKNOWN",
                            lat: 0,
                            lon: 0,
                            region: "UKNW",
                            city: "UKNW",
                            altitudeMode: "",
                            magvar: 0
                        });
                        let n = this.loadingFacilities.indexOf(icao);
                        if (n >= 0) {
                            this.loadingFacilities.splice(n, 1);
                        }
                        callback(undefined);
                    }
                    else {
                        this.instrument.requestCall(checkDataLoaded);
                    }
                }
            };
            checkDataLoaded();
        }
        else {
            this.instrument.requestCall(this.getIntersectionDataCB.bind(this, icao, callback));
        }
    }
    async getIntersectionData(icao) {
        await this.waitRegistration();
        icao = icao.trim();
        let intersection = this.loadedFacilityDatas.find(f => {
            return (f.icaoTrimed === icao) && (f.routes != undefined);
        });
        if (intersection) {
            return intersection;
        }
        let t0 = performance.now();
        if (this.loadingFacilities.indexOf(icao) === -1) {
            Coherent.call("LOAD_INTERSECTION", icao);
            this.loadingFacilities.push(icao);
        }
        return new Promise((resolve) => {
            let attempts = 0;
            let loadedIntersectionCallback = () => {
                let intersection = this.loadedFacilityDatas.find(f => {
                    return (f.icaoTrimed === icao) && (f.routes != undefined);
                });
                if (intersection) {
                    let n = this.loadingFacilities.indexOf(icao);
                    if (n >= 0) {
                        this.loadingFacilities.splice(n, 1);
                    }
                    resolve(intersection);
                }
                else {
                    attempts++;
                    if (attempts > 100) {
                        let n = this.loadingFacilities.indexOf(icao);
                        if (n >= 0) {
                            this.loadingFacilities.splice(n, 1);
                        }
                        resolve(undefined);
                    }
                    else {
                        this.instrument.requestCall(loadedIntersectionCallback);
                    }
                }
            };
            loadedIntersectionCallback();
        });
    }
    async getIntersections(icaos) {
        await this.waitRegistration();
        let intersections = [];
        let datas = await this.getIntersectionsData(icaos);
        if (datas) {
            for (let i = 0; i < datas.length; i++) {
                let intersection = new WayPoint(this.instrument);
                intersection.SetFromIFacility(datas[i]);
                intersections.push(intersection);
            }
        }
        return intersections;
    }
    async getIntersectionsData(icaos) {
        await this.waitRegistration();
        let t0 = performance.now();
        let datas = [];
        for (let i = 0; i < icaos.length; i++) {
            icaos[i] = icaos[i].trim();
        }
        let i = 0;
        let loadingIcaos = [];
        while (i < icaos.length) {
            let icao = icaos[i];
            let intersection = this.loadedFacilityDatas.find(f => {
                return (f.icaoTrimed === icao) && (f.routes != undefined);
            });
            if (intersection) {
                datas.push(intersection);
                icaos.splice(i, 1);
            }
            else {
                if (this.loadingFacilities.find(i => { return i === icao; })) {
                    icaos.splice(i, 1);
                    loadingIcaos.push(icao);
                }
                else {
                    i++;
                }
            }
        }
        if (icaos.length === 0) {
            return datas;
        }
        if (icaos.length > 0) {
            Coherent.call("LOAD_INTERSECTIONS", icaos, icaos.length);
        }
        icaos.push(...loadingIcaos);
        return new Promise((resolve) => {
            let attempts = 0;
            let loadedIntersectionsCallback = () => {
                let i = 0;
                while (i < icaos.length) {
                    let icao = icaos[i];
                    let intersection = this.loadedFacilityDatas.find(f => {
                        return (f.icaoTrimed === icao) && (f.routes != undefined);
                    });
                    if (intersection) {
                        let n = this.loadingFacilities.indexOf(icao);
                        if (n >= 0) {
                            this.loadingFacilities.splice(n, 1);
                        }
                        datas.push(intersection);
                        icaos.splice(i, 1);
                    }
                    else {
                        i++;
                    }
                }
                if (icaos.length === 0) {
                    resolve(datas);
                }
                else {
                    attempts++;
                    if (attempts === 5) {
                        console.warn("Retry to load INTERSECTIONS ICAOS.");
                        Coherent.call("LOAD_INTERSECTIONS", icaos, icaos.length);
                    }
                    if (attempts > 10) {
                        resolve(datas);
                    }
                    else {
                        this.instrument.requestCall(loadedIntersectionsCallback);
                    }
                }
            };
            loadedIntersectionsCallback();
        });
    }
    getNdbDataCB(icao, callback) {
        if (this._isCompletelyRegistered && this.loadingFacilities.length < this._maxSimultaneousCoherentCalls) {
            icao = icao.trim();
            let ndb = this.loadedFacilityDatas.find(f => { return f.icaoTrimed === icao && (f.routes === undefined); });
            if (ndb) {
                return callback(ndb);
            }
            if (icao[0] !== "N") {
                console.warn("Icao mismatch trying to load NDB of invalid icao '" + icao + "'");
            }
            if (this.loadingFacilities.indexOf(icao) === -1) {
                Coherent.call("LOAD_NDB", icao);
                this.loadingFacilities.push(icao);
            }
            let attempts = 0;
            let checkDataLoaded = () => {
                let ndb = this.loadedFacilityDatas.find(f => { return f.icaoTrimed === icao && (f.routes === undefined); });
                if (ndb) {
                    let n = this.loadingFacilities.indexOf(icao);
                    if (n >= 0) {
                        this.loadingFacilities.splice(n, 1);
                    }
                    callback(ndb);
                }
                else {
                    attempts++;
                    if (attempts > 10) {
                        let n = this.loadingFacilities.indexOf(icao);
                        if (n >= 0) {
                            this.loadingFacilities.splice(n, 1);
                        }
                        callback(undefined);
                    }
                    else {
                        this.instrument.requestCall(checkDataLoaded);
                    }
                }
            };
            checkDataLoaded();
        }
        else {
            this.instrument.requestCall(this.getNdbDataCB.bind(this, icao, callback));
        }
    }
    getNdbWaypointDataCB(icao, callback) {
        return this.getIntersectionDataCB(icao, callback);
    }
    async getNdbData(icao) {
        await this.waitRegistration();
        icao = icao.trim();
        let t0 = performance.now();
        let ndb = this.loadedFacilityDatas.find(f => { return f.icaoTrimed === icao && (f.routes === undefined); });
        if (ndb) {
            return ndb;
        }
        if (icao[0] !== "N") {
            console.warn("Icao mismatch trying to load NDB of invalid icao '" + icao + "'");
        }
        if (this.loadingFacilities.indexOf(icao) === -1) {
            Coherent.call("LOAD_NDB", icao);
            this.loadingFacilities.push(icao);
        }
        return new Promise((resolve) => {
            let attempts = 0;
            let loadedNdbCallback = () => {
                let ndb = this.loadedFacilityDatas.find(f => { return f.icaoTrimed === icao && (f.routes === undefined); });
                if (ndb) {
                    let n = this.loadingFacilities.indexOf(icao);
                    if (n >= 0) {
                        this.loadingFacilities.splice(n, 1);
                    }
                    resolve(ndb);
                }
                else {
                    attempts++;
                    if (attempts > 10) {
                        let n = this.loadingFacilities.indexOf(icao);
                        if (n >= 0) {
                            this.loadingFacilities.splice(n, 1);
                        }
                        resolve(undefined);
                    }
                    else {
                        this.instrument.requestCall(loadedNdbCallback);
                    }
                }
            };
            loadedNdbCallback();
        });
    }
    async getNdbs(icaos) {
        await this.waitRegistration();
        let ndbs = [];
        let datas = await this.getNdbsData(icaos);
        if (datas) {
            for (let i = 0; i < datas.length; i++) {
                let ndb = new WayPoint(this.instrument);
                ndb.SetFromIFacility(datas[i]);
                ndbs.push(ndb);
            }
        }
        return ndbs;
    }
    async getNdbsData(icaos) {
        await this.waitRegistration();
        let t0 = performance.now();
        let datas = [];
        for (let i = 0; i < icaos.length; i++) {
            icaos[i] = icaos[i].trim();
        }
        let i = 0;
        while (i < icaos.length) {
            let icao = icaos[i];
            let ndb = this.loadedFacilityDatas.find(f => { return f.icaoTrimed === icao && (f.routes === undefined); });
            if (ndb) {
                datas.push(ndb);
                icaos.splice(i, 1);
            }
            else {
                i++;
            }
        }
        if (icaos.length === 0) {
            return datas;
        }
        for (let i = 0; i < icaos.length; i++) {
            let icao = icaos[i];
            if (icao[0] !== "N") {
                console.warn("Icao mismatch trying to load NDB of invalid icao '" + icao + "'");
            }
        }
        Coherent.call("LOAD_NDBS", icaos, icaos.length);
        return new Promise((resolve) => {
            let attempts = 0;
            let loadedNdbsCallback = () => {
                let i = 0;
                while (i < icaos.length) {
                    let icao = icaos[i];
                    let ndb = this.loadedFacilityDatas.find(f => { return f.icaoTrimed === icao && (f.routes === undefined); });
                    if (ndb) {
                        datas.push(ndb);
                        icaos.splice(i, 1);
                    }
                    else {
                        i++;
                    }
                }
                if (icaos.length === 0) {
                    resolve(datas);
                }
                else {
                    attempts++;
                    if (attempts === 5) {
                        Coherent.call("LOAD_NDBS", icaos, icaos.length);
                    }
                    if (attempts > 10) {
                        resolve(datas);
                    }
                    else {
                        this.instrument.requestCall(loadedNdbsCallback);
                    }
                }
            };
            loadedNdbsCallback();
        });
    }
    getVorDataCB(icao, callback) {
        if (this._isCompletelyRegistered && this.loadingFacilities.length < this._maxSimultaneousCoherentCalls) {
            icao = icao.trim();
            let vor = this.loadedFacilityDatas.find(f => { return f.icaoTrimed === icao && (f.routes === undefined); });
            if (vor) {
                return callback(vor);
            }
            if (icao[0] !== "V") {
                console.warn("Icao mismatch trying to load VOR of invalid icao '" + icao + "'");
            }
            if (this.loadingFacilities.indexOf(icao) === -1) {
                Coherent.call("LOAD_VOR", icao);
                this.loadingFacilities.push(icao);
            }
            let attempts = 0;
            let checkDataLoaded = () => {
                let vor = this.loadedFacilityDatas.find(f => { return f.icaoTrimed === icao && (f.routes === undefined); });
                if (vor) {
                    let n = this.loadingFacilities.indexOf(icao);
                    if (n >= 0) {
                        this.loadingFacilities.splice(n, 1);
                    }
                    callback(vor);
                }
                else {
                    attempts++;
                    if (attempts > 10) {
                        let n = this.loadingFacilities.indexOf(icao);
                        if (n >= 0) {
                            this.loadingFacilities.splice(n, 1);
                        }
                        callback(undefined);
                    }
                    else {
                        this.instrument.requestCall(checkDataLoaded);
                    }
                }
            };
            checkDataLoaded();
        }
        else {
            this.instrument.requestCall(this.getVorDataCB.bind(this, icao, callback));
        }
    }
    getVorWaypointDataCB(icao, callback) {
        return this.getIntersectionDataCB(icao, callback);
    }
    async getVorData(icao) {
        await this.waitRegistration();
        icao = icao.trim();
        let vor = this.loadedFacilityDatas.find(f => { return f.icaoTrimed === icao && (f.routes === undefined); });
        if (vor) {
            return vor;
        }
        let t0 = performance.now();
        if (icao[0] !== "V") {
            console.warn("Icao mismatch trying to load VOR of invalid icao '" + icao + "'");
        }
        if (this.loadingFacilities.indexOf(icao) === -1) {
            Coherent.call("LOAD_VOR", icao);
            this.loadingFacilities.push(icao);
        }
        return new Promise((resolve) => {
            let attempts = 0;
            let loadedVorCallback = () => {
                let vor = this.loadedFacilityDatas.find(f => { return f.icaoTrimed === icao && (f.routes === undefined); });
                if (vor) {
                    let n = this.loadingFacilities.indexOf(icao);
                    if (n >= 0) {
                        this.loadingFacilities.splice(n, 1);
                    }
                    resolve(vor);
                }
                else {
                    attempts++;
                    if (attempts > 10) {
                        let n = this.loadingFacilities.indexOf(icao);
                        if (n >= 0) {
                            this.loadingFacilities.splice(n, 1);
                        }
                        resolve(undefined);
                    }
                    else {
                        this.instrument.requestCall(loadedVorCallback);
                    }
                }
            };
            loadedVorCallback();
        });
    }
    async getVors(icaos) {
        await this.waitRegistration();
        let vors = [];
        let datas = await this.getVorsData(icaos);
        if (datas) {
            for (let i = 0; i < datas.length; i++) {
                let vor = new WayPoint(this.instrument);
                vor.SetFromIFacility(datas[i]);
                vors.push(vor);
            }
        }
        return vors;
    }
    async getVorsData(icaos) {
        await this.waitRegistration();
        let t0 = performance.now();
        let datas = [];
        for (let i = 0; i < icaos.length; i++) {
            icaos[i] = icaos[i].trim();
        }
        let i = 0;
        while (i < icaos.length) {
            let icao = icaos[i];
            let vor = this.loadedFacilityDatas.find(f => { return f.icaoTrimed === icao && (f.routes === undefined); });
            if (vor) {
                datas.push(vor);
                icaos.splice(i, 1);
            }
            else {
                i++;
            }
        }
        if (icaos.length === 0) {
            return datas;
        }
        for (let i = 0; i < icaos.length; i++) {
            let icao = icaos[i];
            if (icao[0] !== "V") {
                console.warn("Icao mismatch trying to load VOR of invalid icao '" + icao + "'");
            }
        }
        Coherent.call("LOAD_VORS", icaos, icaos.length);
        return new Promise((resolve) => {
            let attempts = 0;
            let loadedVorsCallback = () => {
                let i = 0;
                while (i < icaos.length) {
                    let icao = icaos[i];
                    let vor = this.loadedFacilityDatas.find(f => { return f.icaoTrimed === icao && (f.routes === undefined); });
                    if (vor) {
                        datas.push(vor);
                        icaos.splice(i, 1);
                    }
                    else {
                        i++;
                    }
                }
                if (icaos.length === 0) {
                    resolve(datas);
                }
                else {
                    attempts++;
                    if (attempts === 5) {
                        Coherent.call("LOAD_VORS", icaos, icaos.length);
                    }
                    if (attempts > 10) {
                        resolve(datas);
                    }
                    else {
                        this.instrument.requestCall(loadedVorsCallback);
                    }
                }
            };
            loadedVorsCallback();
        });
    }
    async getAllAirways(intersection, maxLength = 10, force = false) {
        await this.waitRegistration();
        let airways = [];
        let intersectionInfo;
        if (intersection instanceof WayPoint) {
            intersectionInfo = intersection.infos;
        }
        else {
            intersectionInfo = intersection;
        }
        if (intersectionInfo instanceof WayPointInfo) {
            let datas = await this.getAllAirwaysData(intersectionInfo, maxLength, force);
            for (let i = 0; i < datas.length; i++) {
                let airway = new Airway();
                airway.SetFromIAirwayData(datas[i]);
                airways.push(airway);
            }
        }
        return airways;
    }
//PM Modif: check maxlength
    async getAllAirwaysData(intersectionInfo, maxLength = 10, force = false) {
        await this.waitRegistration();
        let airways = [];
        if (intersectionInfo.routes) {
            for (let i = 0; i < intersectionInfo.routes.length; i++) {
                let routeName = intersectionInfo.routes[i].name;
                let airwayData = force ? null : this.loadedAirwayDatas.get(routeName);
                if (!airwayData || airwayData.maxLength < maxLength) {
                    airwayData = await this.getAirwayData(intersectionInfo, intersectionInfo.routes[i].name, maxLength);
                    this.loadedAirwayDatas.set(routeName, airwayData);
                }
                if (airwayData) {
                    airways.push(airwayData);
                }
            }
        }
        return airways;
    }
//PM Modif: End check maxlength

//PM Modif: filter airway data by distance to avoid MSFS airways bug and check maxlength
    async getAirwayData(intersectionInfo, name = "", maxLength = 100) {
        await this.waitRegistration();
        if (!intersectionInfo.routes) {
            return undefined;
        }
        if (name === "") {
            name = intersectionInfo.routes[0].name;
        }
        let route = intersectionInfo.routes.find(r => { return r.name === name; });
        if (route) {
            let airway = {
                name: route.name,
                type: route.type,
                icaos: [intersectionInfo.icao],
                maxLength: maxLength
            };
            let lastPrevCoordinates = undefined;
            let lastNextCoordinates = undefined;
            let currentRoute = route;
            for (let i = 0; i < maxLength * 0.5; i++) {
                if (currentRoute) {
                    let prevIcao = currentRoute.prevIcao;
                    currentRoute = undefined;
                    if (prevIcao && prevIcao.length > 0 && prevIcao[0] != " ") {
                        let prevWaypoint = await this.getIntersectionData(prevIcao);
                        if (prevWaypoint) {
                            let ll = new LatLong(prevWaypoint.lat, prevWaypoint.lon);
                            let prevCoordinates = intersectionInfo.coordinates;
                            if(lastPrevCoordinates)
                                prevCoordinates = lastPrevCoordinates;
                            let distance = Avionics.Utils.computeDistance(ll, prevCoordinates);
                            if(distance < 1000) {
                                airway.icaos.splice(0, 0, prevWaypoint.icao);
                                lastPrevCoordinates = ll;
                                if (prevWaypoint.routes) {
                                    currentRoute = prevWaypoint.routes.find(r => { return r.name === name; });
                                }
                            }
                        }
                    }
                }
            }
            currentRoute = route;
            for (let i = 0; i < maxLength * 0.5; i++) {
                if (currentRoute) {
                    let nextIcao = currentRoute.nextIcao;
                    currentRoute = undefined;
                    if (nextIcao && nextIcao.length > 0 && nextIcao[0] != " ") {
                        let nextWaypoint = await this.getIntersectionData(nextIcao);
                        if (nextWaypoint) {
                            let ll = new LatLong(nextWaypoint.lat, nextWaypoint.lon);
                            let nextCoordinates = intersectionInfo.coordinates;
                            if(lastNextCoordinates)
                                nextCoordinates = lastNextCoordinates;
                            let distance = Avionics.Utils.computeDistance(ll, nextCoordinates);
                            if(distance < 1000) {
                                airway.icaos.push(nextWaypoint.icao);
                                lastNextCoordinates = ll;
                                if (nextWaypoint.routes) {
                                    currentRoute = nextWaypoint.routes.find(r => { return r.name === name; });
                                }
                            }
                        }
                    }
                }
            }
            return airway;
        }
    }
}
//PM Modif: End filter airway data by distance to avoid MSFS airways bug

//PM Modif: old version of the waypoint loader
/* class WaypointLoader {
    constructor(_instrument) {
        this.deprecationDelay = 5000;
        this.waypointsCountLimit = 1000;
        this.waypoints = [];
        this._locked = false;
        this._lastMaxItemsSearchCountSyncDate = 0;
        this._maxItemsSearchCountNeedUpdate = true;
        this._maxItemsSearchCount = 200;
        this._lastSearchRangeSyncDate = 0;
        this._searchRangeNeedUpdate = true;
        this._searchRange = 400;
        this._lastSearchOriginSyncDate = 0;
        this._lastSearchOriginLat = 0;
        this._lastSearchOriginLong = 0;
        this._searchOrigin = new LatLong(0, 0);
        this._itemsCountNeedUpdate = true;
        this._itemsNeedUpdate = true;
        this._isLoadingItems = false;
        this._hasUpdatedItems = true;
        this._lastItemCountUpdateDate = 0;
        this._itemsCount = 0;
        this._itemIterator = 0;
        this.SET_ORIGIN_LATITUDE = "";
        this.SET_ORIGIN_LONGITUDE = "";
        this.SET_SEARCH_RANGE = "";
        this.GET_SEARCH_RANGE = "";
        this.SET_MAX_ITEMS = "";
        this.GET_MAX_ITEMS = "";
        this.GET_ITEMS_COUNT = "";
        this.SET_ITEM_INDEX = "";
        this.GET_ITEM_ICAO = "";
        this.GET_ITEM_IDENT = "";
        this.loaderName = "WaypointLoader";
        this.currentMapAngularWidth = 1;
        this.currentMapAngularHeight = 1;
        this.instrument = _instrument;
    }
    slowDown() {
        this.deprecationDelay *= 1.5;
        this.deprecationDelay = Math.min(this.deprecationDelay, WaypointLoader.DEPRECATION_DELAY_MAX);
    }
    speedUp() {
        this.deprecationDelay /= 2;
        this.deprecationDelay = Math.max(this.deprecationDelay, WaypointLoader.DEPRECATION_DELAY_MIN);
    }
    get maxItemsSearchCount() {
        return this._maxItemsSearchCount;
    }
    set maxItemsSearchCount(v) {
        if (this._maxItemsSearchCount !== v) {
            this._maxItemsSearchCountNeedUpdate = true;
            this._maxItemsSearchCount = v;
        }
    }
    get searchRange() {
        return this._searchRange;
    }
    get searchRangeInMeters() {
        return this._searchRange * 1852;
    }
    set searchRange(v) {
        this._searchRangeNeedUpdate = v !== this.searchRange;
        this._searchRange = v;
    }
    get searchLat() {
        return this._searchOrigin.lat;
    }
    set searchLat(v) {
        this._searchOrigin.lat = v;
    }
    get searchLong() {
        return this._searchOrigin.long;
    }
    set searchLong(v) {
        this._searchOrigin.long = v;
    }
    update() {
        if (this._locked) {
            return;
        }
        let t = performance.now();
        if (!this._isLoadingItems) {
            this.maxItemsSearchCount = Math.min(this.maxItemsSearchCount, this.waypointsCountLimit);
            while (this.waypoints.length > this.waypointsCountLimit) {
                this.waypoints.splice(0, 1);
            }
        }
        if (!this._isLoadingItems) {
            let deltaLat = Math.abs(this._searchOrigin.lat - this._lastSearchOriginLat);
            let deltaLong = Math.abs(this._searchOrigin.long - this._lastSearchOriginLong);
            if ((t - this._lastSearchOriginSyncDate) > this.deprecationDelay || deltaLat > this.currentMapAngularHeight * 0.5 || deltaLong > this.currentMapAngularWidth * 0.5) {
                this._locked = true;
                SimVar.SetSimVarValue("C:fs9gps:" + this.SET_ORIGIN_LATITUDE, "degree latitude", this._searchOrigin.lat, this.instrument.instrumentIdentifier + "-loader").then(() => {
                    SimVar.SetSimVarValue("C:fs9gps:" + this.SET_ORIGIN_LONGITUDE, "degree longitude", this._searchOrigin.long, this.instrument.instrumentIdentifier + "-loader").then(() => {
                        this._lastSearchOriginSyncDate = t;
                        this._locked = false;
                        this._itemsCountNeedUpdate = true;
                        this._hasUpdatedItems = false;
                        this._lastSearchOriginLat = this._searchOrigin.lat;
                        this._lastSearchOriginLong = this._searchOrigin.long;
                    });
                });
                return;
            }
            if (this._searchRangeNeedUpdate || (t - this._lastSearchRangeSyncDate) > this.deprecationDelay) {
                this._locked = true;
                SimVar.SetSimVarValue("C:fs9gps:" + this.SET_SEARCH_RANGE, "nautical miles", this.searchRange, this.instrument.instrumentIdentifier + "-loader").then(() => {
                    let trueSearchRange = SimVar.GetSimVarValue("C:fs9gps:" + this.GET_SEARCH_RANGE, "nautical miles", this.instrument.instrumentIdentifier + "-loader");
                    if (Math.abs(trueSearchRange - this.searchRange) < 0.001) {
                        this._searchRangeNeedUpdate = false;
                        this._lastSearchRangeSyncDate = t;
                        this._locked = false;
                        this._itemsCountNeedUpdate = true;
                        this._hasUpdatedItems = false;
                    }
                    else {
                        this.instrument.requestCall(() => {
                            this._locked = false;
                        }, 1000);
                    }
                });
                return;
            }
            if (this._maxItemsSearchCountNeedUpdate || (t - this._lastMaxItemsSearchCountSyncDate) > this.deprecationDelay) {
                this._locked = true;
                SimVar.SetSimVarValue("C:fs9gps:" + this.SET_MAX_ITEMS, "number", this.maxItemsSearchCount, this.instrument.instrumentIdentifier + "-loader").then(() => {
                    let trueMaxItemsSearchCount = SimVar.GetSimVarValue("C:fs9gps:" + this.GET_MAX_ITEMS, "number", this.instrument.instrumentIdentifier + "-loader");
                    if (trueMaxItemsSearchCount === this.maxItemsSearchCount) {
                        if (this._maxItemsSearchCount === 0) {
                            this._searchRangeNeedUpdate = true;
                        }
                        else {
                            this._searchRangeNeedUpdate = false;
                        }
                        this._maxItemsSearchCountNeedUpdate = false;
                        this._lastMaxItemsSearchCountSyncDate = t;
                        this._locked = false;
                        this._itemsCountNeedUpdate = true;
                        this._hasUpdatedItems = false;
                    }
                    else {
                        this.instrument.requestCall(() => {
                            this._locked = false;
                        }, 1000);
                    }
                });
                return;
            }
            if (this._itemsCountNeedUpdate || (t - this._lastItemCountUpdateDate) > this.deprecationDelay) {
                this._itemsCount = SimVar.GetSimVarValue("C:fs9gps:" + this.GET_ITEMS_COUNT, "number", this.instrument.instrumentIdentifier + "-loader");
                this._lastItemCountUpdateDate = t;
                this._itemsCountNeedUpdate = false;
                this._itemsNeedUpdate = true;
                this._hasUpdatedItems = false;
                return;
            }
        }
        if (this._itemsCount > 0) {
            if (this._itemsNeedUpdate) {
                this._locked = true;
                this._isLoadingItems = true;
                if (this.createWaypointsCallback) {
                    if (!this.batch) {
                        if (!this.GET_ITEMS_COUNT || !this.SET_ITEM_INDEX || !this.GET_ITEM_ICAO) {
                            console.error("WaypointLoader : Simvar Batch bad format");
                        }
                        this.batch = new SimVar.SimVarBatch("C:fs9gps:" + this.GET_ITEMS_COUNT, "C:fs9gps:" + this.SET_ITEM_INDEX);
                        this.batch.add("C:fs9gps:" + this.GET_ITEM_ICAO, "string");
                    }
                    let icaos = [];
                    SimVar.GetSimVarArrayValues(this.batch, async (values) => {
                        for (let i = 0; i < values.length; i++) {
                            icaos.push(values[i][0]);
                        }
                        let waypoints = await this.createWaypointsCallback(icaos);
                        if (waypoints && waypoints.length > 0) {
                            this._hasUpdatedItems = true;
                            this.waypoints.push(...waypoints);
                        }
                        else {
                            this._hasUpdatedItems = false;
                        }
                        this._isLoadingItems = false;
                        this._itemIterator = 0;
                        this._itemsNeedUpdate = false;
                        if (this._hasUpdatedItems) {
                            this.speedUp();
                        }
                        else {
                            this.slowDown();
                        }
                        this._locked = false;
                    }, this.instrument.instrumentIdentifier + "-loader");
                }
                else {
                    SimVar.SetSimVarValue("C:fs9gps:" + this.SET_ITEM_INDEX, "number", this._itemIterator, this.instrument.instrumentIdentifier + "-loader").then(async () => {
                        if (this.GET_ITEM_ICAO && this.createWaypointCallback) {
                            let icao = SimVar.GetSimVarValue("C:fs9gps:" + this.GET_ITEM_ICAO, "string", this.instrument.instrumentIdentifier + "-loader");
                            let waypoint = this.waypoints.find(a => { return a.icao === icao; });
                            if (!waypoint) {
                                waypoint = await this.createWaypointCallback(icao);
                                if (waypoint) {
                                    this.waypoints.push(waypoint);
                                    this._hasUpdatedItems = true;
                                }
                            }
                        }
                        else {
                            let ident = SimVar.GetSimVarValue("C:fs9gps:" + this.GET_ITEM_IDENT, "string", this.instrument.instrumentIdentifier + "-loader");
                            let airport = this.waypoints.find(a => { return a.ident === ident; });
                            if (!airport) {
                                airport = await this.createCallback(ident);
                                this.waypoints.push(airport);
                                this._hasUpdatedItems = true;
                            }
                        }
                        this._itemIterator = this._itemIterator + 1;
                        if (this._itemIterator >= this._itemsCount) {
                            this._isLoadingItems = false;
                            this._itemIterator = 0;
                            this._itemsNeedUpdate = false;
                            if (this._hasUpdatedItems) {
                                this.speedUp();
                            }
                            else {
                                this.slowDown();
                            }
                        }
                        this._locked = false;
                    });
                    return;
                }
            }
        }
    }
}

 */

//PM Modif: new version of the waypoint loader based on coherent calls

class WaypointLoader {
    constructor(_instrument) {
        this.deprecationDelay = 5000;
        this.waypointsCountLimit = 1000;
        this.waypoints = [];
        this._maxItemsSearchCountNeedUpdate = true;
        this._maxItemsSearchCount = 200;
        this._lastSyncDate = 0;
        this._searchRangeNeedUpdate = true;
        this._searchRange = 400;
        this._lastSearchOriginLat = 0;
        this._lastSearchOriginLong = 0;
        this._searchOrigin = new LatLong(0, 0);
        this.loaderName = "WaypointLoader";
        this.currentMapAngularWidth = 1;
        this.currentMapAngularHeight = 1;
        this.instrument = _instrument;
        this.searchSessionId = null;
        this._isRegistered = false;
        this._isCompletelyRegistered = false;
        this.initializing = false;
        this.initialized = false;
        this.registerListener();
    }
    registerListener() {
        if (this._isRegistered) {
            return;
        }
        this._isRegistered = true;
        RegisterViewListener("JS_LISTENER_FACILITY", () => {
            console.log("JS_LISTENER_FACILITY registered.");
            Coherent.on("NearestSearchCompleted", (data) => {
                this.onNearestSearchCompleted(data);
            });
            this._isCompletelyRegistered = true;
        }, true);
    }
    async waitRegistration() {
        if (!this._isCompletelyRegistered) {
            let waitForCompleteRegistration = () => {
                return new Promise(resolve => {
                    let f = () => {
                        if (this._isCompletelyRegistered) {
                            resolve();
                        }
                        else {
                            this.instrument.requestCall(f);
                        }
                    };
                    f();
                });
            };
            await waitForCompleteRegistration();
        }
    }
    searchNearest(lat, lon, radius, maxItems) {
        Coherent.call('SEARCH_NEAREST', this.searchSessionId, lat, lon, radius, maxItems);
    }
    async onNearestSearchCompleted(results) {
        if(!this.searchSessionId || !results || results.sessionId != this.searchSessionId)
            return;
        let hasUpdatedItems = false;
        if(results.added.length) {
            let waypoints = await this.createWaypointsCallback(results.added);
            if (waypoints && waypoints.length > 0) {
                hasUpdatedItems = true;
                this.waypoints.push(...waypoints);
            }
        }
        if(results.removed.length) {
            for (let i = 0; i < results.removed.length; i++) {
                let icao = results.removed[i];
                if (icao) {
                    let index = this.waypoints.findIndex(a => { return a.icao === icao; })
                    if (index >= 0) {
                        this.waypoints.splice(index, 1);
                    }
                }
            }
        }
        if (hasUpdatedItems)
            this.speedUp();
        else
            this.slowDown();
    }
    slowDown() {
        this.deprecationDelay *= 1.5;
        this.deprecationDelay = Math.min(this.deprecationDelay, WaypointLoader.DEPRECATION_DELAY_MAX);
    }
    speedUp() {
        this.deprecationDelay /= 2;
        this.deprecationDelay = Math.max(this.deprecationDelay, WaypointLoader.DEPRECATION_DELAY_MIN);
    }
    get maxItemsSearchCount() {
        return this._maxItemsSearchCount;
    }
    set maxItemsSearchCount(v) {
        if (this._maxItemsSearchCount !== v) {
            this._maxItemsSearchCountNeedUpdate = true;
            this._maxItemsSearchCount = v;
        }
    }
    get searchRange() {
        return this._searchRange;
    }
    get searchRangeInMeters() {
        return this._searchRange * 1852;
    }
    set searchRange(v) {
        this._searchRangeNeedUpdate = v !== this.searchRange;
        this._searchRange = v;
    }
    get searchLat() {
        return this._searchOrigin.lat;
    }
    set searchLat(v) {
        this._searchOrigin.lat = v;
    }
    get searchLong() {
        return this._searchOrigin.long;
    }
    set searchLong(v) {
        this._searchOrigin.long = v;
    }
    async update() {
        await this.waitRegistration();
        if(!this.searchSessionId) {
            let type = 0;
            switch (this.loaderName) {
                case "NDBLoader" :
                    type = 4;
                    break;
                case "VORLoader" :
                    type = 3;
                    break;
                case "IntersectionLoader" :
                    type = 2;
                    break;
                case "AirportLoader" :
                    type = 1;
                    break;
                case "AirspaceLoader" :
                    type = 5;
                    break;
                default:
                    type = 0;
            }
            this.searchSessionId = await Coherent.call('START_NEAREST_SEARCH_SESSION', type);
        }
        if(!this.searchSessionId)
            return;
        // let time to initialize
        if(!this.initializing && !this.initialized) {
            this.initializing = true;
            setTimeout(() => {
                if(this.loaderName == "IntersectionLoader")
                    Coherent.call('SET_NEAREST_INTERSECTION_FILTER', this.searchSessionId, 487, 1);
                else if(this.loaderName == "AirspaceLoader")
//                    Coherent.call('SET_NEAREST_BOUNDARY_FILTER', this.searchSessionId, 0x8FC078);
                    Coherent.call('SET_NEAREST_BOUNDARY_FILTER', this.searchSessionId, 0x1C038);
                else if(this.loaderName == "AirportLoader")
                    Coherent.call('SET_NEAREST_AIRPORT_FILTER', this.searchSessionId, 0, 0x3E);
                this.initialized = true;
            }, 1000);
        }
        if(!this.initialized)
            return;

        let t = performance.now();
        this.maxItemsSearchCount = Math.min(this.maxItemsSearchCount, this.waypointsCountLimit);
        while (this.waypoints.length > this.waypointsCountLimit) {
            this.waypoints.splice(0, 1);
        }
        let deltaLat = Math.abs(this._searchOrigin.lat - this._lastSearchOriginLat);
        let deltaLong = Math.abs(this._searchOrigin.long - this._lastSearchOriginLong);
        let doUpdate = false;
        if (t - this._lastSyncDate > this.deprecationDelay)
            doUpdate = true;
        if (this._searchRangeNeedUpdate || this._maxItemsSearchCountNeedUpdate)
            doUpdate = true;            
        if (deltaLat > this.currentMapAngularHeight * 0.5 || deltaLong > this.currentMapAngularWidth * 0.5)
            doUpdate = true;

        if (doUpdate) {
            this._lastSearchOriginLat = this._searchOrigin.lat;
            this._lastSearchOriginLong = this._searchOrigin.long;
            this._searchRangeNeedUpdate = false;
            this._maxItemsSearchCountNeedUpdate = false;
            this.searchNearest(this._searchOrigin.lat, this._searchOrigin.long, this.searchRange * 1852, this.maxItemsSearchCount);
            this._lastSyncDate = t;
        }
    }
}
WaypointLoader.DEPRECATION_DELAY_MAX = 60000;
WaypointLoader.DEPRECATION_DELAY_MIN = 2000;
class NDBLoader extends WaypointLoader {
    constructor(_instrument) {
        super(_instrument);
        this.loaderName = "NDBLoader";
        this.createWaypointsCallback = async (icaos) => {
            let icaosToLoad = [];
            for (let i = 0; i < icaos.length; i++) {
                let icao = icaos[i];
                if (icao) {
                    if (!this.waypoints.find(a => { return a.icao === icao; })) {
                        icaosToLoad.push(icao);
                    }
                }
            }
            return this.instrument.facilityLoader.getNdbs(icaosToLoad);
        };
    }
}
class VORLoader extends WaypointLoader {
    constructor(_instrument) {
        super(_instrument);
        this.loaderName = "VORLoader";
        this.createWaypointsCallback = async (icaos) => {
            let icaosToLoad = [];
            for (let i = 0; i < icaos.length; i++) {
                let icao = icaos[i];
                if (icao) {
                    if (!this.waypoints.find(a => { return a.icao === icao; })) {
                        icaosToLoad.push(icao);
                    }
                }
            }
            return this.instrument.facilityLoader.getVors(icaosToLoad);
        };
    }
}
class IntersectionLoader extends WaypointLoader {
    constructor(_instrument) {
        super(_instrument);
        this.loaderName = "IntersectionLoader";
        this.createWaypointsCallback = async (icaos) => {
            let icaosToLoad = [];
            for (let i = 0; i < icaos.length; i++) {
                let icao = icaos[i];
                if (icao) {
                    if (!this.waypoints.find(a => { return a.icao === icao; })) {
                        icaosToLoad.push(icao);
                    }
                }
            }
            return this.instrument.facilityLoader.getIntersections(icaosToLoad);
        };
    }
}
class AirportLoader extends WaypointLoader {
    constructor(_instrument) {
        super(_instrument);
        this.loaderName = "AirportLoader";
        this.currentMask = 0x3E;
        this.createWaypointsCallback = async (icaos) => {
            let icaosToLoad = [];
            for (let i = 0; i < icaos.length; i++) {
                let icao = icaos[i];
                if (icao) {
                    if (!this.waypoints.find(a => { return a.icao === icao; })) {
                        icaosToLoad.push(icao);
                    }
                }
            }
            return this.instrument.facilityLoader.getAirports(icaosToLoad);
        };
    }
    async update() {
        super.update();
        if(this.initialized) {
            let newFilterMask = 0x3E;
            if(this.instrument && this.instrument.aircraftType) {
                if(this.instrument.appm2307635.appm2307632()) {
                    if(this.instrument.aircraftType == 1)
                        newFilterMask = 0x26;
                    else if(this.instrument.aircraftType == 2)
                        newFilterMask = 0x36;
                    else if(this.instrument.aircraftType == 3)
                        newFilterMask = 0x22;
                    else if(this.instrument.aircraftType == 4)
                        newFilterMask = 0x2E;
                }
            }
            if(newFilterMask != this.currentMask) {
                this.currentMask = newFilterMask;
                Coherent.call('SET_NEAREST_AIRPORT_FILTER', this.searchSessionId, 0, this.currentMask);

            }
        }
    }
}
class AirspaceLoader extends WaypointLoader {
    constructor(_instrument) {
        super(_instrument);
        this.loaderName = "AirspaceLoader";
        this.createWaypointsCallback = async (airspaces) => {
            let airspacesToReturn = [];
            let currentAltitude = SimVar.GetSimVarValue("GPS POSITION ALT", "feet");
            let currentAltitudeAGL = SimVar.GetSimVarValue("PLANE ALT ABOVE GROUND", "feet");
            let deltaAltitude = 3000;
            for (let i = 0; i < airspaces.length; i++) {
                let airspace = airspaces[i];
                if (airspace) {
                    var newairspace = new NearestAirspace();
                    newairspace.name = Utils.Translate(airspace.name);
                    newairspace.ident = (newairspace.name + "_" + i).replace(new RegExp(" ", "g"), "");
                    newairspace.ident = newairspace.ident.replace(new RegExp("/", "g"), "");
                    newairspace.type = airspace.type;
                    newairspace.status = -1;
                    newairspace.nearDistance = -1;
                    newairspace.aheadTime = -1;
                    newairspace.geometry = -1;
                    newairspace.minAltitude = Math.floor(airspace.minAlt * 3.28084);
                    newairspace.maxAltitude = Math.min(60000, Math.floor(airspace.maxAlt * 3.28084));
                    newairspace.frequency = airspace.frequency.freqMHz;
                    let centerCoordinates = new LatLong((airspace.topLeft.lat + airspace.bottomRight.lat) / 2, (airspace.topLeft.long + airspace.bottomRight.long) / 2);
                    let radius = Avionics.Utils.computeDistance(airspace.topLeft, airspace.bottomRight) / 2;
                    newairspace.distanceToCenter = Avionics.Utils.computeDistance(this._searchOrigin, centerCoordinates);
                    newairspace.distanceToBorder = newairspace.distanceToCenter - radius;

                    let altitudeOk = true;
                    if(airspace.minAltType == 1) {
                        if(currentAltitude + deltaAltitude < newairspace.minAltitude)
                            altitudeOk = false;
                    }
                    else if(airspace.minAltType == 2) {
                        if(currentAltitudeAGL + deltaAltitude < newairspace.minAltitude)
                            altitudeOk = false;
                    }
                    if(airspace.maxAltType == 1) {
                        if(currentAltitude - deltaAltitude > newairspace.maxAltitude)
                            altitudeOk = false;
                    }
                    else if(airspace.minAltType == 2) {
                        if(currentAltitudeAGL - deltaAltitude > newairspace.maxAltitude)
                            altitudeOk = false;
                    }
                    if(airspacesToReturn.findIndex(el => { return el.name === newairspace.name;}) == -1 && newairspace.distanceToBorder <= this.searchRange && altitudeOk)
                        airspacesToReturn.push(newairspace);
                }
            }
            airspacesToReturn.sort((a,b) => Math.abs(a.distanceToCenter) - Math.abs(b.distanceToCenter));
            return airspacesToReturn;
        };
    }
}

//# sourceMappingURL=WaypointLoader.js.map