"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.MpvnetXmlSerializer = void 0;
const fast_xml_builder_1 = __importDefault(require("fast-xml-builder"));
const moment_timezone_1 = __importDefault(require("@golemio/core/dist/shared/moment-timezone"));
const InfotextDisplayTypeEnum_1 = require("../domain/InfotextDisplayTypeEnum");
const HeadsignFormatter_1 = require("../service/helpers/HeadsignFormatter");
const MpvnetTransportTypeMapper_1 = require("./MpvnetTransportTypeMapper");
const PRAGUE_TIMEZONE = "Europe/Prague";
const ARROW_UNICODE = /→/g;
const ARROW_ASCII = "->";
const ISO_LOCAL_FORMAT = "YYYY-MM-DDTHH:mm:ss";
const ISO_LOCAL_OFFSET_FORMAT = "YYYY-MM-DDTHH:mm:ssZ";
// Omit > from escapes so the literal "->" arrow (mapped from unicode →) survives in the smer attribute.
const XML_ENTITIES_KEEP_GT = [
    { regex: /&/g, val: "&amp;" },
    { regex: /</g, val: "&lt;" },
    { regex: /'/g, val: "&apos;" },
    { regex: /"/g, val: "&quot;" },
];
class MpvnetXmlSerializer {
    static serialize(dto) {
        const tree = {
            TBL: {
                "@_cas": MpvnetXmlSerializer.formatTblCas(new Date()),
                "@_text": "Odjezdy poskytuje Golemio",
                t: MpvnetXmlSerializer.buildStopNode(dto),
            },
        };
        return MpvnetXmlSerializer.builder.build(tree);
    }
    static buildStopNode(dto) {
        const rawZast = dto.stops[0]?.stop_name ?? "";
        const node = {
            "@_id": MpvnetXmlSerializer.formatStopIds(dto.stops),
            "@_zast": rawZast,
            "@_zobraz_stan": "True",
            "@_stan": MpvnetXmlSerializer.formatPlatformListCsv(dto.stops),
        };
        if (dto.departures.length > 0) {
            node.o = dto.departures.map((d) => MpvnetXmlSerializer.buildDeparture(d));
        }
        if (dto.infotexts.length > 0) {
            node.i = dto.infotexts.map((info) => MpvnetXmlSerializer.buildInfotext(info, dto.stops));
        }
        return node;
    }
    static buildDeparture(departure) {
        const lin = departure.route.short_name ?? "";
        const dd = String((0, MpvnetTransportTypeMapper_1.mapTransportType)({
            type: departure.route.type,
            is_night: departure.route.is_night,
            is_regional: departure.route.is_regional,
            is_substitute_transport: departure.route.is_substitute_transport,
        }));
        const out = {};
        if (departure.stop.platform_code) {
            out["@_stan"] = departure.stop.platform_code;
        }
        out["@_lin"] = lin;
        out["@_alias"] = lin;
        out["@_spoj"] = MpvnetXmlSerializer.extractTrainNumber(departure.trip.short_name);
        out["@_smer"] = MpvnetXmlSerializer.formatSmer(lin, departure.trip.headsign);
        out["@_odj"] = MpvnetXmlSerializer.formatScheduledOffset(departure.departure_timestamp.scheduled);
        out["@_sled"] = String(departure.delay.is_available);
        out["@_zpoz"] = String(departure.delay.minutes ?? 0);
        out["@_np"] = String(departure.trip.is_wheelchair_accessible ?? false);
        out["@_nad"] = String(departure.route.is_substitute_transport);
        if (departure.trip.is_canceled) {
            out["@_info"] = "nejede";
        }
        if (departure.trip.is_at_stop) {
            out["@_blik"] = "true";
        }
        if (departure.last_stop.name) {
            out["@_pz"] = departure.last_stop.name;
        }
        out["@_smer_c"] = "0";
        out["@_dd"] = dd;
        return out;
    }
    static buildInfotext(infotext, stops) {
        const stan = MpvnetXmlSerializer.formatPlatformListTab(stops);
        const text = infotext.text_en ? `${infotext.text} / ${infotext.text_en}` : infotext.text;
        if (infotext.display_type === InfotextDisplayTypeEnum_1.InfotextDisplayType.General) {
            return { "@_stan": stan, "@_global": "true", "@_ds": "GLOBAL_STATIC", "#text": text };
        }
        return { "@_stan": stan, "#text": text };
    }
    static formatTblCas(date) {
        return moment_timezone_1.default.tz(date, PRAGUE_TIMEZONE).format(ISO_LOCAL_FORMAT);
    }
    static formatScheduledOffset(isoString) {
        if (!isoString) {
            return "";
        }
        return moment_timezone_1.default.tz(isoString, PRAGUE_TIMEZONE).format(ISO_LOCAL_OFFSET_FORMAT);
    }
    // Strip the airport pictogram (HeadsignFormatter) and replace the unicode arrow with ASCII for legacy MPVnet panels.
    static formatHeadsign(headsign) {
        return HeadsignFormatter_1.HeadsignFormatter.format(headsign).replace(ARROW_UNICODE, ARROW_ASCII);
    }
    // For MHD lines (local Kolín city bus) strip the "Kolín, " city prefix from the headsign
    static formatSmer(linShortName, headsign) {
        const formatted = MpvnetXmlSerializer.formatHeadsign(headsign);
        return linShortName.startsWith("MHD") ? formatted.replace(/^Kolín,\s*/, "") : formatted;
    }
    // Trip number is the last numeric run of trip.short_name (e.g. "S9 1234" -> "1234", "1234" -> "1234").
    static extractTrainNumber(shortName) {
        return shortName?.match(/\d+/g)?.pop() ?? "";
    }
    static formatPlatformListCsv(stops) {
        return MpvnetXmlSerializer.collectPlatformCodes(stops).join(",");
    }
    static formatPlatformListTab(stops) {
        return MpvnetXmlSerializer.collectPlatformCodes(stops).join("\t");
    }
    static collectPlatformCodes(stops) {
        const codes = stops.map((s) => s.platform_code ?? "").filter((c) => c.length > 0);
        return [...new Set(codes)].sort();
    }
    static formatStopIds(stops) {
        const ids = stops.map((s) => {
            if (s.asw_id && s.asw_id.node != null && s.asw_id.stop != null) {
                return `${s.asw_id.node}/${s.asw_id.stop}`;
            }
            return s.stop_id;
        });
        return [...new Set(ids)].sort().join(",");
    }
}
exports.MpvnetXmlSerializer = MpvnetXmlSerializer;
MpvnetXmlSerializer.builder = new fast_xml_builder_1.default({
    ignoreAttributes: false,
    attributeNamePrefix: "@_",
    suppressEmptyNode: true,
    suppressBooleanAttributes: false,
    format: false,
    processEntities: true,
    entities: XML_ENTITIES_KEEP_GT,
});
//# sourceMappingURL=MpvnetXmlSerializer.js.map