const { errorCode } = require("../constant");
const KHQRSubtag = require("../constant/KHQRSubtag");
const KHQRTag = require("../constant/KHQRTag");
const cutString = require("../helper/cutString");
const { KHQRResponse } = require("../model");

/**
 * Decode helper function
 * This decode funcition has a flow of
 * 1. Slice the string as each KHQR tag and store into memory
 * 2. Check if the required field exist
 * 3. Check if the KHQR Code given is in order or not
 * 4. Get the value of each tag and if there is subtag repeat number 1
 * @param {string} KHQRString
 * @returns object of KHQR decode
 */
function decodeKHQR(KHQRString) {
    const allField = KHQRTag.map((el) => el.tag);
    const subtag = KHQRTag.filter((el) => el.sub == true).map((obj) => obj.tag);
    let requiredField = KHQRTag.filter((el) => el.required == true).map(
        (el) => el.tag
    );
    const subTagInput = KHQRSubtag.input;
    const subTagCompare = KHQRSubtag.compare;

    let tags = {};
    let merchantType = null;
    let lastTag = "";

    while (KHQRString) {
        sliceTagObject = cutString(KHQRString);
        let { tag, value, slicedString } = sliceTagObject;

        if (tag == lastTag) break;

        const isMerchant = tag == "30";

        if (isMerchant) {
            merchantType = "30";
            tag = "29";
        } else if (tag == "29") merchantType = "29";

        if (allField.includes(tag)) {
            tags[tag] = value;
            requiredField = requiredField.filter((el) => el != tag);
        }

        KHQRString = slicedString;
        lastTag = tag;
    }

    // const requiredFieldNotExist = requiredField.length != 0;
    // if (requiredFieldNotExist) {
    //     const requiredTag = requiredField[0];
    //     const missingInstance = findTag(KHQRTag, requiredTag).instance;
    //     new missingInstance(requiredTag, null);
    // }

    // const khqrInOrder = isInorder(
    //     tags.map((e) => parseInt(e.tag)).splice(-1, 1)
    // );

    // if (!khqrInOrder) throw KHQRResponse(null, errorCode.TAG_NOT_IN_ORDER);

    let decodeValue = {
        merchantType: merchantType,
    };

    subTagInput
        .map((el) => el.data)
        .forEach((obj) => (decodeValue = { ...decodeValue, ...obj }));
    KHQRTag.forEach((khqrTag) => {
        const tag = khqrTag.tag;
        const khqr = KHQRTag.find((el) => el.tag == tag);
        let value = tags[tag] == undefined ? null : tags[tag];
        let inputValue = value;
        if (subtag.includes(tag)) {
            const inputdata = findTag(subTagInput, tag).data;
            while (value) {
                cutsubstring = cutString(value);
                const subtag = cutsubstring.tag;
                const subtagValue = cutsubstring.value;
                const slicedsubtag = cutsubstring.slicedString;

                let nameSubtag = subTagCompare
                    .filter((el) => el.tag == tag)
                    .find((el) => el.subTag == subtag);

                if (nameSubtag != undefined) {
                    nameSubtag = nameSubtag.name;
                    inputdata[nameSubtag] = subtagValue;
                    inputValue = inputdata;
                }
                value = slicedsubtag;
            }
            try {
                new khqr.instance(tag, inputValue);
            } catch (error) {}
        } else {
            decodeValue[khqr.type] = value;
            if (tag == "99" && value == null) decodeValue[khqr.type] = null;
        }
    });

    return decodeValue;
}

/**
 * Helper function for decode
 * It query from the object where tag is the same
 */
const findTag = (object, tag) => object.find((el) => el.tag == tag);

/**
 * Check if the array is in order algorithm
 */
const isInorder = (a) => a.slice(1).every((e, i) => e > a[i]);

module.exports = decodeKHQR;
