const MamiColour = (() => {
    const readThres = 168;
    const lumiRed = .299;
    const lumiGreen = .587;
    const lumiBlue = .114;

    const pub = {};

    const extractRGB = raw => [
        (raw >> 16) & 0xFF,
        (raw >> 8) & 0xFF,
        raw & 0xFF,
    ];

    const luminance = raw => {
        const rgb = extractRGB(raw);
        return rgb[0] * lumiRed
             + rgb[1] * lumiGreen
             + rgb[2] * lumiBlue;
    };

    const weightedNumber = (num1, num2, weight) => {
        weight = Math.min(1, Math.max(0, weight));
        return Math.round((num1 * weight) + (num2 * (1 - weight)));
    };

    const weighted = (raw1, raw2, weight) => {
        const rgb1 = extractRGB(raw1);
        const rgb2 = extractRGB(raw2);
        return (weightedNumber(rgb1[0], rgb2[0], weight) << 16)
            | (weightedNumber(rgb1[1], rgb2[1], weight) << 8)
            | weightedNumber(rgb1[2], rgb2[2], weight);
    };

    pub.extractRGB = extractRGB;
    pub.weightedNumber = weightedNumber;
    pub.luminance = luminance;
    pub.weighted = weighted;

    pub.text = raw => luminance(raw) > readThres ? 0 : 0xFFFFFF;

    pub.shaded = (raw, offset) => {
        if(offset == 0)
            return raw;

        let dir = 0xFFFFFF;
        if(offset < 0) {
            dir = 0;
            offset *= -1;
        }

        return weighted(dir, raw, offset);
    };

    pub.hexByte = raw => {
        let str = raw.toString(16).substring(0, 2);
        return str.length < 2
            ? `0${str}` : str;
    };

    pub.hex = raw => {
        let str = raw.toString(16).substring(0, 6);
        if(str.length < 6)
            str = '000000'.substring(str.length) + str;
        return `#${str}`;
    };

    pub.fromHex = str => {
        while(str.substring(0, 1) === '#')
            str = str.substring(1);
        str = str.substring(0, 6);

        if(str.length === 3)
            str = str.substring(0, 1) + str.substring(0, 1)
                + str.substring(1, 2) + str.substring(1, 2)
                + str.substring(2, 3) + str.substring(2, 3);

        if(str.length !== 6)
            throw 'not a valid hex string';

        return parseInt(str, 16);
    };

    return pub;
})();
