/*
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

var trackingcoderegex = /^[0-9a-zA-Z]{5,40}$/;

function openTrackingInfoPage(code) {
    if (typeof code == "undefined" || code == null || code.trim() == "") {
        app.input.validate("#trackingcode");
        app.toast.show({
            text: "Please enter a tracking code.",
            position: "bottom",
            closeTimeout: 2000
        });
        return;
    }

    router.navigate("/track/" + code);
}

function addTrackingSuggestions() {
    $("#tracking-history-list ul").html("");
    $("#tracking-history-list-empty").addClass("display-none");
    $("#tracking-history-list .list").removeClass("display-none");
    var history = getTrackingHistory();
    if (history == false || history.length == 0) {
        $("#tracking-history-list-empty").removeClass("display-none");
        $("#tracking-history-list .list").addClass("display-none");
    } else {
        for (var i = history.length - 1; i >= 0; i--) {
            $("#tracking-history-list ul").append('<li><a class="item-link item-content hapticbtn tracking-code-history-link" data-trackingcode="' + history[i] + '" href="/track/' + history[i] + '">'
                    + '<div class="item-inner"><div class="item-title">'
                    + history[i]
                    + '</div></div></a></li>');
        }
    }
    if (inStorage("accountkey") && inStorage("accountnumber")) {
        $("#tracking-account-list-empty").addClass("display-none");
        $("#tracking-account-list .list").removeClass("display-none");
        apirequest(SETTINGS.apis.gettrackingnumbers, {
            accountnumber: getStorage("accountnumber"),
            accountkey: getStorage("accountkey")
        }, function (success) {
            if (success.status == "OK") {
                $("#tracking-account-list ul").html("");
                for (var i = 0; i < success.trackingnumbers.length; i++) {
                    $("#tracking-account-list ul").append('<li><a class="item-link item-content hapticbtn" href="/track/' + success.trackingnumbers[i].trackingcode + '">'
                            + '<div class="item-inner">'
                            + '<div class="item-title">'
                            + '<div class="item-header">' + success.trackingnumbers[i].nickname + '</div>'
                            + success.trackingnumbers[i].trackingcode
                            + '<div class="item-footer">' + success.trackingnumbers[i].datetimestring + '</div>'
                            + '</div>'
                            + '</div></a></li>');
                }

                if (success.trackingnumbers.length == 0) {
                    $("#tracking-account-list-empty").removeClass("display-none");
                    $("#tracking-account-list .list").addClass("display-none");
                }
            } else {
                $("#tracking-account-list ul").html('<li class="item-content"><div class="item-inner justify-content-center"><div class="item-title" style="color: var(--f7-list-item-footer-text-color);">Error: ' + success.msg + '</div></div></li>');
            }
        }, function (xhr, status, error) {
            $("#tracking-account-list ul").html('<li class="item-content"><div class="item-inner justify-content-center"><div class="item-title" style="color: var(--f7-list-item-footer-text-color);">Server or network error. Try again later.</div></div></li>');
            sendErrorReport("Tracking", "Couldn't get account tracking codes", "Server/network problem: " + xhr.status + ": " + xhr.statusText);
        }, "GET");
    } else {
        $("#tracking-account-list-empty").removeClass("display-none");
        $("#tracking-account-list .list").addClass("display-none");
    }

    $("#tracking-multi-list-empty").addClass("display-none");
    $("#tracking-multi-list .list").removeClass("display-none");
    var codes = getTrackingMultiList();
    if (codes.length > 0) {
        $("#tracking-multi-list ul").html('<li class="item-content"><div class="item-inner justify-content-center text-align-center noselect">Loading...</div></li>');
        // Only update if we're on that tab, since it's not the easiest API call for the server to do
        if ($("#tracking-multi-list").hasClass("tab-active")) {
            updateTrackingMultiListStatus();
        }
    } else {
        $("#tracking-multi-list-empty").removeClass("display-none");
        $("#tracking-multi-list .list").addClass("display-none");
    }
}

function updateTrackingMultiListStatus() {
    var codes = getTrackingMultiList();
    console.log(codes.length);
    $("#tracking-multi-list-empty").addClass("display-none");
    $("#tracking-multi-list .list").removeClass("display-none");
    $("#tracking-multi-list ul").html('<li class="item-content"><div class="item-inner justify-content-center"><div class="item-title">Loading...</div></div></li>');
    if (codes.length > 0) {
        $("#tracking-multi-list ul").html("");
        for (var i = 0; i < codes.length; i++) {
            $("#tracking-multi-list ul").append('<li><div style="cursor: pointer;" class="item-content tracking-code-multi-link noselect" data-trackingcode="' + codes[i].code + '" onclick="router.navigate(\'/track/' + codes[i].code + '\')">'
                    + '<div class="item-inner item-cell">'
                    + (codes[i].nick == "" ? "" : '<div class="item-row"><div class="item-cell"><b>' + codes[i].nick + '</b></div></div>')
                    + '<div class="item-row"><div class="item-cell">' + codes[i].code + '</div></div>'
                    + '<div class="item-row"><div class="item-cell">'
                    + '<img src="" class="trackingeventicon tracking-multi-status-icon" /> <span class="tracking-multi-status-text"></span>'
                    + '</div></div></div></div></li>');
        }
        var codelist = [];
        for (var i = 0; i < codes.length; i++) {
            codelist.push(codes[i].code);
        }
        apirequest(SETTINGS.apis.trackmultiple, {
            code: codelist.join(",")
        }, function (resp) {
            if (resp.status == "OK") {
                for (const code in resp.results) {
                    $(".tracking-code-multi-link[data-trackingcode=\"" + code + "\"] .tracking-multi-status-text").text(resp.results[code].text);
                    $(".tracking-code-multi-link[data-trackingcode=\"" + code + "\"] .tracking-multi-status-icon").attr("src", "./assets/images/icons/" + resp.results[code].icon + ".svg");
                }

                $("#tracking-multi-list ul").append('<li class="item-content"><div class="item-inner display-block text-align-center noselect" style="color: var(--f7-list-item-footer-text-color);"><i class="fas fa-info-circle"></i>&nbsp;<span class="taptext">Long-press</span><span class="clicktext">Right-click</span>&nbsp;an entry to remove it.</div></li>');
            } else {
                $("#tracking-multi-list ul").html('<li class="item-content"><div class="item-inner justify-content-center text-align-center noselect">Error: ' + resp.msg + '</div></li>');
                sendErrorReport("Tracking", "Couldn't get multi tracking", resp.msg);
            }
        }, function (xhr) {
            try {
                var resp = $.parseJSON(xhr.responseText);
                if (resp && typeof resp.msg != 'undefined') {
                    $("#tracking-multi-list ul").html('<li class="item-content"><div class="item-inner justify-content-center text-align-center">Error: ' + resp.msg + '</div></li>');
                    sendErrorReport("Tracking", "Couldn't get multi tracking", resp.msg);
                } else {
                    $("#tracking-multi-list ul").html('<li class="item-content"><div class="item-inner justify-content-center text-align-center noselect">There\'s a server or network problem. Check your Internet connection or try again later.</div></li>');
                    sendErrorReport("Tracking", "Couldn't get multi tracking", "Server/network problem: " + xhr.status + ": " + xhr.statusText);
                }
            } catch (ex) {
                $("#tracking-multi-list ul").html('<li class="item-content"><div class="item-inner justify-content-center text-align-center noselect">There\'s a server or network problem. Check your Internet connection or try again later.</div></li>');
                sendErrorReport("Tracking", "Couldn't get multi tracking", "Server/network problem: " + xhr.status + ": " + xhr.statusText);
            }
        });

    } else {
        $("#tracking-multi-list-empty").removeClass("display-none");
        $("#tracking-multi-list .list").addClass("display-none");
    }
}

function openTrackingBarcodeScanner() {
    scanBarcode(function (result) {
        var code = "";
        if (result.startsWith("https://helena.express/track#")) {
            code = result.split("#")[1];
        } else if (result.startsWith("http") && result.includes("#")) {
            if (trackingcoderegex.test(result.split("#")[1])) {
                code = result.split("#")[1];
            } else {
                app.dialog.alert("This app can't understand what's in that barcode.", "Error");
                return;
            }
        } else if (trackingcoderegex.test(result)) {
            code = result;
        } else {
            app.dialog.alert("This app can't understand what's in that barcode.", "Error");
            return;
        }
        code = code.toUpperCase();
        openTrackingInfoPage(code);
    }, function () {
        app.dialog.alert("Something went wrong and we can't scan right now.", "Error");
    });
}

function trackOpenAsync( {to, resolve, reject}) {
    app.dialog.preloader("Loading...");

    apirequest(
            SETTINGS.apis.track,
            {
                code: to.params.code,
                format: "json"
            },
            function (resp) {
                app.dialog.close();
                if (resp.status == "OK") {
                    addToTrackingHistory(resp.code);

                    var context = {
                        code: resp.code,
                        info: [
                            {label: "Tracking Code", value: resp.code},
                        ],
                        events: [],
                        map: {
                            enabled: (typeof resp.info.latitude == "number" && typeof resp.info.longitude == "number" && MapControl.supported()),
                            latitude: resp.info.latitude,
                            longitude: resp.info.longitude,
                            accurate: resp.info.geoaccurate
                        }
                    };
                    if (resp.info.statustext) {
                        context.info.push({label: "Status", value: resp.info.statustext});
                    }
                    if (resp.info.carrier) {
                        if (resp.info.carrier_logo) {
                            context.info.push({label: "Carrier", value: "<img style=\"height: 2em; padding: 0.667em; max-width: 80%; background-color: white; border-radius: 0.25em; margin-top: 0.5em;\" src=\"" + resp.info.carrier_logo + "\" />"});
                        } else {
                            context.info.push({label: "Carrier", value: resp.info.carrier});
                        }
                    }
                    if (resp.info.delivery_date) {
                        var deliverydatelabel = "Estimated delivery on";
                        if (resp.info.status == "DELIVERED") {
                            deliverydatelabel = "Delivered on";
                        }
                        context.info.push({label: deliverydatelabel, value: formatTimestamp("F j Y", resp.info.delivery_date_unixtime)});
                    }
                    if (resp.info.carrier_tracking_url) {
                        context.carrierurl = resp.info.carrier_tracking_url;
                    }
                    if (resp.info.carrier_attribution) {
                        context.carrier_attribution = resp.info.carrier_attribution;
                    }

                    for (var i = 0; i < resp.events.length; i++) {
                        context.events.push({
                            text: resp.events[i].text,
                            date: resp.events[i].timestring,
                            icon: "./assets/images/icons/" + resp.events[i].icon + ".svg"
                        });
                    }

                    if (context.events.length == 0) {
                        context.events = false;
                    }

                    sendActionReport("Tracking", "Tracked package");
                    resolve({
                        content: compiledPages.trackresult(context)
                    });
                } else {
                    app.dialog.alert(resp.msg, "Error");
                    sendErrorReport("Tracking", "Couldn't get tracking", resp.msg);
                    reject();
                }
            },
            function (xhr) {
                app.dialog.close();
                try {
                    var error = $.parseJSON(xhr.responseText);
                    if (error && typeof error.msg != 'undefined') {
                        app.dialog.alert(error.msg, "Error");
                        sendErrorReport("Tracking", "Couldn't get tracking", error.msg);
                    } else {
                        app.dialog.alert("There's a server or network problem. Check your Internet connection or try again later.", "Error");
                        sendErrorReport("Tracking", "Couldn't get tracking", "Server/network problem: " + xhr.status + ": " + xhr.statusText);
                    }
                } catch (ex) {
                    app.dialog.alert("There's a server or network problem. Check your Internet connection or try again later.", "Error");
                    sendErrorReport("Tracking", "Couldn't get tracking", "Server/network problem: " + xhr.status + ": " + xhr.statusText);
                }
                reject();
            }, "GET");
}

$("#app").on("submit", "#tracking-searchbar-form", function (evt) {
    evt.preventDefault();

    openTrackingInfoPage($('input[name=\'trackingcode\']').val());

    return false;
});

$("#app").on("contextmenu taphold", ".tracking-code-history-link", function (evt) {
    evt.preventDefault();

    // Don't trigger contextmenu on a touch device because we'll also get a taphold
    if (evt.type == "contextmenu" && window.matchMedia("(pointer: coarse)").matches) {
        return;
    }

    var code = $(this).data("trackingcode");

    var action = app.actions.create({
        buttons: [
            [
                {
                    text: 'Track',
                    bold: true,
                    onClick: function () {
                        openTrackingInfoPage(code);
                    }
                },
                {
                    text: 'Add to Multi list',
                    onClick: function () {
                        addToTrackingMultiList(code);
                        addTrackingSuggestions();
                    }
                },
                {
                    text: 'Remove From History',
                    onClick: function () {
                        removeFromTrackingHistory(code);
                        addTrackingSuggestions();
                    }
                }
            ],
            [
                {
                    text: 'Cancel',
                    color: 'red'
                }
            ]
        ]
    });

    action.open();
    return false;
});

$("#app").on("contextmenu taphold", ".tracking-code-multi-link", function (evt) {
    evt.preventDefault();

    // Don't trigger contextmenu on a touch device because we'll also get a taphold
    if (evt.type == "contextmenu" && window.matchMedia("(pointer: coarse)").matches) {
        return;
    }

    var code = $(this).data("trackingcode");

    var action = app.actions.create({
        buttons: [
            [
                {
                    text: 'Open',
                    bold: true,
                    onClick: function () {
                        openTrackingInfoPage(code);
                    }
                },
                {
                    text: 'Add/Change Nickname',
                    onClick: function () {
                        app.dialog.prompt("Set a nickname for " + code, "Package Name", function (input) {
                            addNicknameToTrackingMultiList(code, htmlEntities(input));
                            updateTrackingMultiListStatus();
                        }, function () {
                            // canceled
                        }, "");
                    }
                },
                {
                    text: 'Remove from list',
                    onClick: function () {
                        removeFromTrackingMultiList(code);
                        addTrackingSuggestions();
                    }
                }
            ],
            [
                {
                    text: 'Cancel',
                    color: 'red'
                }
            ]
        ]
    });

    action.open();
    return false;
});

$("#app").on("contextmenu taphold", "#brokenscannercodeadd", function (evt) {
    evt.preventDefault();

    // Don't trigger contextmenu on a touch device because we'll also get a taphold
    if (evt.type == "contextmenu" && window.matchMedia("(pointer: coarse)").matches) {
        return;
    }

    var code = $('input[name=\'trackingcode\']').val().trim().replace(/\s/, "");

    var action = app.actions.create({
        buttons: [
            [
                {
                    text: 'Track',
                    bold: true,
                    onClick: function () {
                        if (code == "") {
                            app.dialog.alert("You need to type a tracking code first.", "Error");
                            return;
                        }
                        openTrackingInfoPage(code);
                    }
                },
                {
                    text: 'Add to Multi list',
                    onClick: function () {
                        if (code == "") {
                            app.dialog.alert("You need to type a tracking code first.", "Error");
                            return;
                        }
                        if (!code.match(trackingcoderegex)) {
                            app.dialog.alert("That doesn't seem like a valid tracking code.", "Error");
                            return;
                        }
                        addToTrackingMultiList(code);
                        addTrackingSuggestions();
                    }
                }
            ],
            [
                {
                    text: 'Cancel',
                    color: 'red'
                }
            ]
        ]
    });

    action.open();
    return false;
});

$("#app").on("tab:show", "#tracking-multi-list", function (evt) {
    updateTrackingMultiListStatus();
});

function getTrackingHistory() {
    var history = getStorage("trackinghistory");
    if (history == "false" || history == "null" || history == null) {
        return [];
    } else {
        return JSON.parse(history);
    }
}

function addToTrackingHistory(code) {
    var history = getTrackingHistory();

    for (var i = 0; i < history.length; i++) {
        if (history[i] == code) {
            history.splice(i, 1);
        }
    }
    // Add the code back to the list so it's at the top
    history.push(code);

    while (history.length > 10) {
        history.shift();
    }
    setStorage("trackinghistory", JSON.stringify(history));
}

function removeFromTrackingHistory(code) {
    var history = getTrackingHistory();

    for (var i = 0; i < history.length; i++) {
        if (history[i] == code) {
            history.splice(i, 1);
        }
    }

    while (history.length > 10) {
        history.shift();
    }
    setStorage("trackinghistory", JSON.stringify(history));

    $(".tracking-code-history-link[data-trackingcode=\"" + code + "\"]").parent("li").remove();
}


function getTrackingMultiList() {
    var multilist = getStorage("multitrackingcodes");

    if (multilist == "false" || multilist == "null" || multilist == null) {
        return [];
    } else {
        var multilistjson = JSON.parse(multilist);

        if (multilistjson.length > 0) {
            if (typeof multilistjson[0] == "object") {
                return multilistjson;
            } else {
                // Old version is just string array, new version is array of objects,
                // do a conversion
                // TODO: Remove this code once everyone's updated to this version, since it's not efficient to do typeof every time
                var newmultilist = [];
                for (var i = 0; i < multilistjson.length; i++) {
                    newmultilist.push({
                        code: multilistjson[i],
                        nick: ""
                    });
                }
                setStorage("multitrackingcodes", JSON.stringify(newmultilist));
                return newmultilist;
            }
        } else {
            return [];
        }
    }
}

function addToTrackingMultiList(code, nickname) {
    if (typeof nickname != "string") {
        nickname = "";
    }
    var multilist = getTrackingMultiList();

    for (var i = 0; i < multilist.length; i++) {
        if (multilist[i].code == code) {
            // Already in list, remove so we can add with the new nick if set
            multilist.splice(i, 1);
        }
    }
    // Add the code to the list
    multilist.push({
        code: code,
        nick: nickname
    });

    setStorage("multitrackingcodes", JSON.stringify(multilist));
}

function addNicknameToTrackingMultiList(code, nickname) {
    var multilist = getTrackingMultiList();

    for (var i = 0; i < multilist.length; i++) {
        if (multilist[i].code == code) {
            multilist[i].nick = nickname;
        }
    }

    setStorage("multitrackingcodes", JSON.stringify(multilist));
}

function removeFromTrackingMultiList(code) {
    var multilist = getTrackingMultiList();

    for (var i = 0; i < multilist.length; i++) {
        if (multilist[i].code == code) {
            multilist.splice(i, 1);
        }
    }

    setStorage("multitrackingcodes", JSON.stringify(multilist));

    $(".tracking-code-multi-link[data-trackingcode=\"" + code + "\"]").parent("li").remove();
}