//import { parse } from "url";

// https://stackoverflow.com/questions/2998784/how-to-output-integers-with-leading-zeros-in-javascript
export function pad(num: number, size: number) {
    var s = num + "";
    while (s.length < size) s = "0" + s;
    return s;
}

// https://stackoverflow.com/questions/11409895/whats-the-most-elegant-way-to-cap-a-number-to-a-segment
export function clamp(val: number, min: number, max: number) {
    return Math.min(Math.max(val, min), max);
}

// time data in 24 hours
export class Time {
    hours = 0;
    mins = 0;

    constructor(hr: number, mn: number) {
        this.hours = clamp(hr, 0, 23);
        this.mins = clamp(mn, 0, 59);
    }

    to12Hour() {
        let hours = this.hours;
        let mer = "AM";
        if (hours >= 12) {
            hours -= 12;
            mer = "PM";
        }
        if (hours == 0) hours = 12;

        return pad(hours, 2) + ":" + pad(this.mins, 2) + " " + mer.toUpperCase();
    }

    to24Hour() {
        return pad(this.hours, 2) + ":" + pad(this.mins, 2);
    }
}

function parseDateAsText(timeString: string, format?: "24hr" | "12hr") {
    let newTime = "";
    // https://stackoverflow.com/questions/2031085/how-can-i-check-if-string-contains-characters-whitespace-not-just-whitespace
    if (/\S/.test(timeString) || timeString !== "") {
        const t = convertInput(timeString);
        if (!format || format === "12hr") {
            newTime = t.to12Hour();
        } else {
            newTime = t.to24Hour();
        }
    }

    return newTime;
}

/*
1p => 1:00 PM
12p => 12:00 PM
13p => 1:00 PM
130p => 1:30 PM

sungle and double digits:
1 - 24 => convert to 24 hour

triple digits:
130 => 1:30
125 => 1:25

quadruple digits:
0530 => 5:30 // strip trailing zero
1555 => 15:55


if pm and hours > 12: hours += 12

- if no p is present, AM is implied
*/
function convertInput(timeString: string) {
    var meridian = findMeridian(timeString);

    // strip extra characters
    timeString = timeString.replace(/\D/g, "");

    if (timeString.length == 0) return new Time(0, 0);
    if (timeString.length == 1 || timeString.length == 2) return convertSingleAndDouble(timeString, meridian);
    if (timeString.length == 3) return convertTriple(timeString, meridian);
    if (timeString.length == 4) return convertQuadruple(timeString, meridian);

    return new Time(0, 0);
}

// returns am, pm or an empty string if neither is found
function findMeridian(timeString: string): "am" | "pm" | null {
    timeString = timeString.toLowerCase();
    if (timeString.search("pm") !== -1 || timeString.search("p") !== -1) return "pm";
    if (timeString.search("am") !== -1 || timeString.search("a") !== -1) return "am";
    return null;
}

function convertSingleAndDouble(timeString: string, meridian: "am" | "pm" | null) {
    var value = parseInt(timeString) % 24;
    if (meridian === "pm" && value < 12) value += 12;
    if (meridian === "am" && value >= 12) value -= 12;
    return new Time(value % 24, 0);
}

/*
only handles time between 1:01 and 9:99
*/
function convertTriple(timeString: string, meridian: "am" | "pm" | null) {
    var hours = parseInt(timeString.substr(0, 1));
    if (meridian === "pm") hours += 12;

    var mins = parseInt(timeString.substr(1, 3));

    return new Time(hours, mins);
}

function convertQuadruple(timeString: string, meridian: "am" | "pm" | null) {
    var hours = parseInt(timeString.substr(0, 2));
    if (meridian === "pm" && hours < 12) hours += 12;
    if (meridian === "am" && hours >= 12) hours -= 12;
    var mins = parseInt(timeString.substr(2, 5));

    return new Time(hours, mins);
}

// https://stackoverflow.com/questions/8282266/how-to-prevent-invalid-characters-from-being-typed-into-input-fields
export function filterInput(e: any) {
    const inputLength = e.target.value.length;

    // 0-9
    if (e.which > 47 && e.which < 58) {
        return false;
    }

    // https://stackoverflow.com/questions/2353550/how-to-capture-a-backspace-on-the-onkeydown-event/2353562
    // backspace, delete, tab and arrow keys
    if (e.which === 8 || e.which === 46 || e.which === 9 || (e.which >= 37 && e.which <= 40)) {
        return false;
    }

    let key = e.key.toUpperCase();
    // AMP
    /* ensures that the first charater in the input box can not be any of the allowed letters */
    if ((inputLength > 0 && key === "A") || (inputLength > 0 && key === "P") || (inputLength > 0 && key === "M")) {
        return false;
    }

    // colon :
    /* ensures that the first charater in the input box can not be a colon */
    if (inputLength > 0 && e.key === ":") {
        return false;
    }

    e.preventDefault();
}

export function parse(timeString: string, format?: "24hr" | "12hr"): string {
    return parseDateAsText(timeString, format);
}

//export default FastTimeInput;
