const getGroupToCurrency = (group: string) => {
    // necessary arrays needed to convert from numbers to currency
    const basics = [
        'cero',
        'un',
        'dos',
        'tres',
        'cuatro',
        'cinco',
        'seis',
        'siete',
        'ocho',
        'nueve',
        'diez',
        'once',
        'doce',
        'trece',
        'catorce',
        'quince',
    ];
    const teens = [
        '',
        'dieci',
        'veinti',
        'treinta',
        'cuarenta',
        'cincuenta',
        'sesenta',
        'setenta',
        'ochenta',
        'noventa',
    ];
    const hundreds = [
        '',
        'ciento',
        'doscientos',
        'trescientos',
        'cuatrocientos',
        'quinientos',
        'seiscientos',
        'setecientos',
        'ochocientos',
        'novecientos',
    ];
    // variable used to temporarly store currency
    let toCurrency = '';
    // handle hundreds
    if (group.length === 3) {
        switch (parseInt(group, 10)) {
            case 100:
                return 'cien ';
            case 0:
                return '';
            default:
                toCurrency += `${hundreds[parseInt(group[0], 10)]} `;
        }
        // eslint-disable-next-line
        group = group.substring(1, 3);
    }
    // handle teens and 'basic' numbers
    if (parseInt(group, 10) <= 15) {
        // if group is less than 15, select from basics array
        if (group === '00') {
            return toCurrency;
        }
        toCurrency += `${basics[parseInt(group, 10)]} `;
    } else {
        // else look for the number in both teens and basics arrays
        const zeroAtTheEnd = group[1] === '0';
        switch (parseInt(group, 10)) {
            case 20:
                return `${toCurrency}veinte `;
            default:
                toCurrency += `${
                    teens[parseInt(group[0], 10)] +
                    (parseInt(group[0], 10) >= 3 && !zeroAtTheEnd ? ' y ' : '') +
                    (zeroAtTheEnd ? '' : basics[parseInt(group[1], 10)])
                } `;
        }
    }
    // return result
    return toCurrency;
};

const toCurrency = (num: number, moneda?: string): Promise<string> => {
    return new Promise<string>((resolve, reject) => {
        // number to string
        const number = num.toFixed(2);
        // separate decimals (only 2) and integers
        let integers = number.substring(0, number.indexOf('.'));
        const decimals = number.substring(number.indexOf('.') + 1, number.length);
        const monedaName = !moneda || moneda === 'MXN' ? 'M.N.' : moneda;
        // intitalize string to store currency
        let numberToCurrency = '';
        // some helpful variables
        let noThouhsands = false;
        let noHundreds = false;
        let thousandsOfMillions = false;
        // Maximum supported number is 999,999,999,999.99
        if (integers.length <= 12) {
            // evaluate each group of 3 digitis (hundreds, thousands, millions, thousans of millions)
            // evaluate thousands of millions
            if (integers.length === 12 || integers.length === 11 || integers.length === 10) {
                const group = integers.substring(0, integers.length - 9);
                thousandsOfMillions = true;
                switch (parseInt(group, 10)) {
                    case 0:
                        break;
                    case 1:
                        numberToCurrency += 'mil ';
                        break;
                    default:
                        numberToCurrency += `${getGroupToCurrency(group)}mil `;
                }
                integers = integers.substring(integers.length - 9, integers.length);
            }
            // evaluate millions
            if (integers.length === 9 || integers.length === 8 || integers.length === 7) {
                const group = integers.substring(0, integers.length - 6);
                numberToCurrency += getGroupToCurrency(group);
                if (!thousandsOfMillions && parseInt(group, 10) === 1) {
                    numberToCurrency += 'millon ';
                } else {
                    numberToCurrency += 'millones ';
                }
                integers = integers.substring(integers.length - 6, integers.length);
            }
            // evaluate thousands
            if (integers.length === 6 || integers.length === 5 || integers.length === 4) {
                const group = integers.substring(0, integers.length - 3);
                noThouhsands = parseInt(group, 10) === 0;
                switch (parseInt(group, 10)) {
                    case 0:
                        break;
                    case 1:
                        numberToCurrency += 'mil ';
                        break;
                    default:
                        numberToCurrency += `${getGroupToCurrency(group)}mil `;
                }
                integers = integers.substring(integers.length - 3, integers.length);
            }
            // evaluate hundreds
            noHundreds = parseInt(integers, 10) === 0;
            numberToCurrency += getGroupToCurrency(integers);
            numberToCurrency += `${
                (noThouhsands && noHundreds ? 'de ' : '') + (numberToCurrency === 'un ' ? 'peso ' : 'pesos ') + decimals
            }/100 ${monedaName}`;
            resolve(numberToCurrency.toUpperCase());
        }
        reject('Error: el número es demasiado grande.');
    });
};

export { toCurrency };
