/*
 * Copyright 2020 Netsyms Technologies.
 * 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/.
 */

/**
 * Generate a UUID.
 * From https://stackoverflow.com/a/2117523
 * @returns {String}
 */
function uuidv4() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
        var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
        return v.toString(16);
    });
}

/**
 * Perform a request against the API server. A simple wrapper around $.ajax().
 *
 * If username and password are strings, they will be used to authenticate.
 *
 * @param {string} action Request action
 * @param {array} data AJAX data to POST
 * @param {function} success
 * @param {function} error
 * @param {string|undefined} username
 * @param {string|undefined} password
 * @returns {jqXHR}
 */
function apirequest(action, data, success, error, username, password) {
    return $.ajax({
        url: SETTINGS.apiserver + action,
        dataType: "json",
        method: "POST",
        data: data,
        timeout: 10 * 1000,
        beforeSend: function (xhr) {
            if (typeof username === 'string' && typeof password === 'string') {
                xhr.setRequestHeader("Authorization", "Basic " + btoa(username + ":" + password));
            }
        },
        success: function (val) {
            if (typeof success == 'function') {
                success(val);
            }
        },
        error: error
    });
}

/**
 * Take a UNIX timestamp (seconds since Jan 1 1970) and format it.
 * (Mostly) compatible with PHP's date() function.
 * @param {String} date format string, see https://www.php.net/manual/en/function.date.php
 * @param {Integer} timestamp UNIX timestamp
 * @return {String}
 */
function formatTimestamp(format, timestamp) {
    if (typeof timestamp == "undefined") {
        timestamp = time();
    }
    var date = new Date(timestamp * 1000);

    var out = "";

    var months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
    var days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
    for (var i = 0; i < format.length; i++) {
        var c = format.charAt(i);
        // Handle backslash-escaped characters
        if (c == "\\" && i < format.length - 1) {
            out += format.charAt(i + 1);
            i++;
            continue;
        }
        switch (c) {
            case "d":
                var d = date.getDate();
                if (d < 10) {
                    out += "0";
                }
                out += d;
                break;
            case "D":
                out += days[date.getDay()].substring(0, 3);
                break;
            case "j":
                out += date.getDate();
                break;
            case "l":
                out += days[date.getDay()];
                break;
            case "N":
                // TODO
                break;
            case "S":
                // TODO
                break;
            case "w":
                out += date.getDay();
                break;
            case "z":
                // TODO
                break;
            case "W":
                // TODO
                break;
            case "F":
                out += months[date.getMonth()];
                break;
            case "m":
                var m = date.getMonth() + 1;
                if (m < 10) {
                    out += "0";
                }
                out += m;
                break;
            case "M":
                out += months[date.getMonth()].substring(0, 3);
                break;
            case "n":
                out += date.getMonth() + 1;
                break;
            case "t":
                // TODO
                break;
            case "L":
                // TODO
                break;
            case "o":
                // TODO
                break;
            case "Y":
                out += date.getFullYear();
                break;
            case "y":
                var y = (date.getFullYear() + "");
                out += y.substring(y.length - 2);
                break;
            case "a":
                if (date.getHours() < 12) {
                    out += "am";
                } else {
                    out += "pm";
                }
                break;
            case "A":
                if (date.getHours() < 12) {
                    out += "AM";
                } else {
                    out += "PM";
                }
                break;
            case "B":
                // TODO
                break;
            case "g":
                var h = date.getHours() % 12;
                if (h == 0) {
                    h = 12;
                }
                out += h;
                break;
            case "G":
                out += date.getHours();
                break;
            case "h":
                var h = date.getHours() % 12;
                if (h == 0) {
                    h = 12;
                }
                if (h < 10) {
                    out += "0";
                }
                out += h;
                break;
            case "H":
                var h = date.getHours();
                if (h < 10) {
                    out += "0";
                }
                out += h;
                break;
            case "i":
                var ii = date.getMinutes();
                if (ii < 10) {
                    out += "0";
                }
                out += ii;
                break;
            case "s":
                var s = date.getSeconds();
                if (s < 10) {
                    out += "0";
                }
                out += s;
                break;
            case "u":
                out += date.getMilliseconds() * 1000;
                break;
            case "v":
                out += date.getMilliseconds();
                break;
            case "e":
                // TODO
                break;
            case "I":
                // TODO
                break;
            case "O":
                var off = date.getTimezoneOffset();
                var m = off % 60;
                var h = (off - m) / 60;
                if (off >= 0) {
                    out += "+";
                } else {
                    out += "-";
                }
                if (h < 10) {
                    out += "0";
                }
                out += h;
                if (m < 10) {
                    out += "0";
                }
                out += m;
                break;
            case "P":
                var off = date.getTimezoneOffset();
                var m = off % 60;
                var h = (off - m) / 60;
                if (off >= 0) {
                    out += "+";
                } else {
                    out += "-";
                }
                if (h < 10) {
                    out += "0";
                }
                out += h;
                out += ":";
                if (m < 10) {
                    out += "0";
                }
                out += m;
                break;
            case "T":
                // TODO
                break;
            case "Z":
                out += date.getTimezoneOffset() * 60;
                break;
            case "c":
                out += formatTimestamp(timestamp, "Y-m-d\\TH:i:sP");
                break;
            case "r":
                out += formatTimestamp(timestamp, "D, j M Y G:i:s O");
                break;
            case "U":
                out += Math.round(timestamp);
                break;
            default:
                out += c;
        }
    }

    return out;
}

function timestampToDateTimeString(timestamp) {
    return timestampToDateString(timestamp) + " " + timestampToTimeString(timestamp);
}

function timestampToDateString(timestamp) {
    var date = new Date(timestamp * 1000);

    return date.toLocaleDateString();
}

function timestampToTimeString(timestamp) {
    var date = new Date(timestamp * 1000);

    var pm = date.getHours() >= 12;
    var hours = date.getHours() > 12 ? date.getHours() - 12 : date.getHours();
    hours = (hours == 0 ? 12 : hours);
    var minutes = date.getMinutes();
    var time = hours + ":" + (minutes < 10 ? "0" + minutes : minutes) + " " + (pm ? "PM" : "AM");

    return time;
}

/**
 * Get the current UNIX timestamp in seconds.
 * @returns {Number}
 */
function time() {
    return Date.now() / 1000;
}

/**
 * Get the number of seconds between now and the given timestamp.
 * @param {Number} compareto
 * @returns {Number}
 */
function timeDiff(compareto) {
    return time() - compareto;
}