/**
 * @fileOverview Hindi(HIV5.0) keyboard driver.
 * @author <a href="mailto:drachels@drachels.com">AL Rachels</a>
 * @version 4.1
 * @since 20220128
 */

/**
 * Check for combined character.
 * @param {string} chr The combined character.
 * @returns {string} The character.
 */
function isCombined(chr) {
    return false;
}

/**
 * Process keyup for combined character.
 * @param {string} e The combined character.
 * @returns {bolean} The result.
 */
function keyupCombined(e) {
    return false;
}

/**
 * Process keyupFirst.
 * @param {string} event Type of event.
 * @returns {bolean} The event.
 */
function keyupFirst(event) {
    return false;
}

/**
 * Normalize Hindi multi-codepoint key outputs so one physical key highlights correctly.
 * @param {string} ltr The current expected character.
 * @param {number} [pos] Optional text index for token lookahead.
 * @returns {string}
 */
function hindiDisplayToken(ltr, pos) {
    var basePos = (typeof pos === 'number') ? pos : currentPos;

    if (!ltr || typeof fullText === 'undefined' || typeof basePos === 'undefined') {
        return ltr;
    }

    // Number-row shifted outputs that are stored as multiple codepoints in lesson text.
    if (ltr === 'र' && fullText[basePos + 1] === '्') {
        return 'र्';
    }
    if (ltr === 'ज' && fullText[basePos + 1] === '्' && fullText[basePos + 2] === 'ञ') {
        return 'ज्ञ';
    }
    if (ltr === 'त' && fullText[basePos + 1] === '्' && fullText[basePos + 2] === 'र') {
        return 'त्र';
    }
    if (ltr === 'क' && fullText[basePos + 1] === '्' && fullText[basePos + 2] === 'ष') {
        return 'क्ष';
    }
    if (ltr === 'श' && fullText[basePos + 1] === '्' && fullText[basePos + 2] === 'र') {
        return 'श्र';
    }
    if (ltr === 'य' && fullText[basePos + 1] === '़') {
        return 'य़';
    }

    return ltr;
}

/**
 * Check for character typed so flags can be set.
 * @param {string} ltr The current letter.
 */
function keyboardElement(ltr, pos) {
    var keytoken = hindiDisplayToken(ltr, pos);
    this.chr = keytoken.toLowerCase();
    this.alt = false;
    //if (isLetter(ltr)) { // Verify this is a unicode letter.
    //    const shiftrightchars = ['ऍ', 'ॅ', 'र्', 'ज्ञ', 'औ', 'ऐ', 'आ', 'ई', 'ऊ', 'ओ', 'ए', 'अ', 'इ', 'उ', 'ँ', 'ण'];
    //    const shiftleftchars = ['त्र', 'क्ष', 'श्र', '(', ')', 'ः', 'ऋ', 'भ', 'ङ', 'घ', 'ध', 'झ', 'ढ', 'ञ', 'ऑ', 'फ', 'ऱ', 'ख', 'थ', 'छ', 'ठ', 'ळ', 'श', 'ष', '।', 'य़', 'य़'];
    //    if (shiftrightchars.includes(ltr)) {
    //        this.shiftright = true; // Left-side keys use right shift (jkeyshiftd).
    //    } else if (shiftleftchars.includes(ltr)) {
    //        this.shiftleft = true; // Right-side keys use left shift (jkeyshiftl).
    //    }
    //}
    this.shiftright = false;
    this.shiftleft = false;

    const shiftrightchars = ['ऍ', 'ॅ', 'र्', 'ज्ञ', 'औ', 'ऐ', 'आ', 'ई', 'ऊ', 'ओ', 'ए', 'अ', 'इ', 'उ', 'ँ', 'ण'];
    const shiftleftchars = ['त्र', 'क्ष', 'श्र', '(', ')', 'ः', 'ऋ', 'भ', 'ङ', 'घ', 'ध', 'झ', 'ढ', 'ञ', 'ऑ', 'फ', 'ऱ', 'ख', 'थ', 'छ', 'ठ', 'ळ', 'श', 'ष', '।', 'य़', 'य़'];

    // Left-side keys (1-5, Q-T, A-G, X-C) require right shift (jkeyshiftd).
    if (shiftrightchars.includes(keytoken)) {
        this.shiftright = true;
    // Right-side keys (6-0, -, =, Y-], H-\, N-/) require left shift (jkeyshiftl).
    } else if (shiftleftchars.includes(keytoken)) {
        this.shiftleft = true;
    }

    this.turnOn = function() {
        if (isLetter(this.chr)) {
            document.getElementById(getKeyID(this.chr)).className = "next" + thenFinger(this.chr.toLowerCase());
        } else if (this.chr === ' ') {
            document.getElementById(getKeyID(this.chr)).className = "nextSpace";
        } else {
            document.getElementById(getKeyID(this.chr)).className = "next" + thenFinger(this.chr.toLowerCase());
        }
        if (this.chr === '\n' || this.chr === '\r\n' || this.chr === '\n\r' || this.chr === '\r') {
            document.getElementById('jkeyenter').className = "next4";
        }
        if (this.shiftright) {
            document.getElementById('jkeyshiftd').className = "next4";
        }
        if (this.shiftleft) {
            document.getElementById('jkeyshiftl').className = "next4";
        }
    };
    this.turnOff = function() {
        if (isLetter(this.chr)) {
        // phpcs:ignore
            if (this.chr.match(/[ोे्िरकतच]/i)) {
                document.getElementById(getKeyID(this.chr)).className = "finger" + thenFinger(this.chr.toLowerCase());
            } else {
                document.getElementById(getKeyID(this.chr)).className = "normal";
            }
        } else {
            document.getElementById(getKeyID(this.chr)).className = "normal";
        }
        if (this.chr === '\n' || this.chr === '\r\n' || this.chr === '\n\r' || this.chr === '\r') {
            document.getElementById('jkeyenter').className = "normal";
        }
        if (this.shiftright) {
            document.getElementById('jkeyshiftd').className = "normal";
        }
        if (this.shiftleft) {
            document.getElementById('jkeyshiftl').className = "normal";
        }
    };
}

/**
 * Set color flag based on current character.
 * @param {string} tCrka The current character.
 * @returns {number}.
 */
function thenFinger(tCrka) {
    if (tCrka === ' ') {
        return 5; // Highlight the spacebar.
    }

    // Use exact token membership so multi-codepoint Hindi clusters map reliably.
    const finger4chars = ['1', 'ऍ', '0', ')', '-', 'ः', 'ृ', 'ऋ', 'ौ', 'औ',
        'प', 'फ', 'ज', 'झ', 'ड', 'ढ', '़', 'ञ', 'ो', 'ओ', 'च', 'छ',
        'ट', 'ठ', 'ॉ', 'ऑ', 'य', 'य़', 'य़'];
    const finger3chars = ['2', 'ॅ', '9', '(', 'ै', 'ऐ', 'े', 'ए', 'द', 'ध',
        'त', 'थ', 'ं', 'ँ', '.', '।'];
    const finger2chars = ['3', '्', '8', 'श्र', 'ा', 'आ', 'अ', 'म', 'ण',
        'ग', 'घ', 'क', 'ख', ',', 'ष'];
    const finger1chars = ['4', 'र्', '5', 'ज्ञ', '6', 'त्र', '7', 'क्ष',
        'ि', 'ी', 'ई', 'ु', 'ू', 'उ', 'ऊ', 'इ', 'न', 'व', 'ब', 'भ',
        'ल', 'ळ', 'ह', 'ङ', 'र', 'ऱ', 'स', 'श'];

    if (finger4chars.includes(tCrka)) {
        return 4; // Highlight the correct key above in red.
    } else if (finger3chars.includes(tCrka)) {
        return 3; // Highlight the correct key above in green.
    } else if (finger2chars.includes(tCrka)) {
        return 2; // Highlight the correct key above in yellow.
    } else if (finger1chars.includes(tCrka)) {
        return 1; // Highlight the correct key above in blue.
    } else {
        return 6; // Do not change any highlight.
    }
}

/**
 * Get ID of key to highlight based on current character.
 * @param {string} tCrka The current character.
 * @returns {string}.
 */
function getKeyID(tCrka) {
    if (tCrka === ' ') {
        return "jkeyspace";
    } else if (tCrka === '\n') {
        return "jkeyenter";
    } else if (tCrka === '1' || tCrka === 'ऍ') {
        return "jkey1";
    } else if (tCrka === '2' || tCrka === 'ॅ') {
        return "jkey2";
    } else if (tCrka === '3') {
        return "jkey3";
    } else if (tCrka === '4' || tCrka === 'र्') {
        return "jkey4";
    } else if (tCrka === '5' || tCrka === 'ज्ञ') {
        return "jkey5";
    } else if (tCrka === '6' || tCrka === 'त्र') {
        return "jkey6";
    } else if (tCrka === '7' || tCrka === 'क्ष') {
        return "jkey7";
    } else if (tCrka === '8' || tCrka === 'श्र') {
        return "jkey8";
    } else if (tCrka === '9' || tCrka === '(') {
        return "jkey9";
    } else if (tCrka === '0' || tCrka === ')') {
        return "jkey0";
    } else if (tCrka === '-' || tCrka === 'ः') {
        return "jkeyminus";
    } else if (tCrka === 'ृ' || tCrka === 'ऋ') {
        return "jkeyequals";
    } else if (tCrka === 'ौ' || tCrka === 'औ') {
        return "jkeyq";
    } else if (tCrka === 'ै' || tCrka === 'ऐ') {
        return "jkeyw";
    } else if (tCrka === 'ा' || tCrka === 'आ') {
        return "jkeye";
    } else if (tCrka === 'ी' || tCrka === 'ई') {
        return "jkeyr";
    } else if (tCrka === 'ू' || tCrka === 'ऊ') {
        return "jkeyt";
    } else if (tCrka === 'ब' || tCrka === 'भ') {
        return "jkeyy";
    } else if (tCrka === 'ह' || tCrka === 'ङ') {
        return "jkeyu";
    } else if (tCrka === 'ग' || tCrka === 'घ') {
        return "jkeyi";
    } else if (tCrka === 'द' || tCrka === 'ध') {
        return "jkeyo";
    } else if (tCrka === 'ज' || tCrka === 'झ') {
        return "jkeyp";
    } else if (tCrka === 'ड' || tCrka === 'ढ') {
        return "jkeybracketl";
    } else if (tCrka === '़' || tCrka === 'ञ') {
        return "jkeybracketr";
    } else if (tCrka === 'ो' || tCrka === 'ओ') {
        return "jkeya";
    } else if (tCrka === 'े' || tCrka === 'ए') {
        return "jkeys";
    } else if (tCrka === '्' || tCrka === 'अ') {
        return "jkeyd";
    } else if (tCrka === 'ि' || tCrka === 'इ') {
        return "jkeyf";
    } else if (tCrka === 'ु' || tCrka === 'उ') {
        return "jkeyg";
    } else if (tCrka === 'प' || tCrka === 'फ') {
        return "jkeyh";
    } else if (tCrka === 'र' || tCrka === 'ऱ') {
        return "jkeyj";
    } else if (tCrka === 'क' || tCrka === 'ख') {
        return "jkeyk";
    } else if (tCrka === 'त' || tCrka === 'थ') {
        return "jkeyl";
    } else if (tCrka === 'च' || tCrka === 'छ') {
        return "jkeysemicolon";
    } else if (tCrka === 'ट' || tCrka === 'ठ') {
        return "jkeyapostrophe";
    } else if (tCrka === 'ॉ' || tCrka === 'ऑ') {
        return "jkeybackslash";
    } else if (tCrka === 'ं' || tCrka === 'ँ') {
        return "jkeyx";
    } else if (tCrka === 'म' || tCrka === 'ण') {
        return "jkeyc";
    } else if (tCrka === 'न') {
        return "jkeyv";
    } else if (tCrka === 'व') {
        return "jkeyb";
    } else if (tCrka === 'ल' || tCrka === 'ळ') {
        return "jkeyn";
    } else if (tCrka === 'स' || tCrka === 'श') {
        return "jkeym";
    } else if (tCrka === ',' || tCrka === 'ष') {
        return "jkeycomma";
    } else if (tCrka === '.' || tCrka === '।') {
        return "jkeyperiod";
    } else if (tCrka === 'य' || tCrka === 'य़' || tCrka === 'य़') {
        return "jkeyslash";
    } else {
        return "jkey" + tCrka;
    }
}

/**
 * Is the typed letter part of the current alphabet.
 * @param {string} str The current letter.
 * @returns {(number|Array)}.
 */
function isLetter(str) {
    return str.length === 1 && str.match(/[!-ﻼ]/i);
}
