import {
    ImageOptions
} from "./types";

class Images {
    readonly baseCdnUrl: string;
    readonly cdnIgnoreUrl: string[];
    readonly cdnAllowUrl: string[];

    constructor(options: ImageOptions) {
        this.baseCdnUrl = options.baseCdnUrl;
        this.cdnIgnoreUrl = [
            'localhost',
            '.test',
            '.vn',
            '.local',
            'liveview.printerval.com',
            'amazon.com',
            'printerval.com/unsafe',
            'printerval.megaads.vn',
            'image.spreadshirtmedia.com',
            'd1q9av5b648rmv.cloudfront.net',
            'cdn.shopify.com',
            '.jfif',
            '.avif',
            '.jfif',
            '.pjpeg',
            '.pjp',
            '.tif',
            '.tiff',
            '.ico',
            '.cur',
            '.bmp',
            '.gif',
            'ai-designer.printerval.com',
            'rlv.zcache.com'
        ].map((url) => {
            return this.crypt('megaads', url);
        });
        this.cdnAllowUrl = [
            'printerval.com',
            'assets.printerval.com',
            'seller.printerval.com',
            'storage.googleapis.com',
            'asset.prtvstatic.com',
            'i.etsystatic.com',
            'redbubble.net',
            'cdn.customily.com',
            'cdn.teeinblue.com',
            'res.cloudinary.com'
        ].map((url) => {
            return this.crypt('megaads', url);
        });
    }

    getImageCdn($url: string, $width = 0, $height = 0, $fitIn = false, $webp = false, filters: any): string {
        $fitIn = false;

        if ($url && !$url.match(/\.(jpg|jpeg|png|gif)$/i)) {
            return $url;
        }

        let zoomIn = '';
        if (!$url) {
            return $url;
        }

        if ($url.indexOf('http') != 0) {
            if ($url.indexOf('//') != 0) {
                if ($url.indexOf('/') != 0) {
                    $url = 'https://' + $url;
                } else {
                    $url = window.location.origin + $url;
                }
            } else {
                $url = 'http:' + $url;
            }
        }

        const sizePattern = new RegExp(/(image|blank|sticker|unsafe)\/\d+x\d+/);
        if (sizePattern.test($url)) {
            return $url;
        }

        const regex = /^https?:\/\/[^/]+(\/[^?#]*)/;
        const match = regex.exec($url);
        const path = match && match[1];
        if (path && (path.startsWith("/image/") || path.startsWith("/blank/") || path.startsWith("/sticker/"))) {
            if (!$width) $width = $height;
            $url = $url.replace('/blank/', '/blank/' + $width + 'x' + $width + '/');
            $url = $url.replace('/image/', '/image/' + $width + 'x' + $width + '/');
            $url = $url.replace('/sticker/', '/sticker/' + $width + 'x' + $width + '/');
            $url = this.replaceImageUrl($url);
            return $url;
        }

        $url = this.replaceImageUrl($url);
        if (($width == 1260 && $height == 0) || ($width == 0 && $height == 0)) {
            return $url;
        }
        let tempCdnIgnoreUrl = this.cdnIgnoreUrl.map((url) => {
            return this.decrypt('megaads', url);
        })

        let tempCdnAllowUrl = this.cdnAllowUrl.map((url) => {
            return this.decrypt('megaads', url);
        })

        if (typeof tempCdnIgnoreUrl !== 'undefined') {
            for (let item of tempCdnIgnoreUrl) {
                if ($url.includes(item)) {
                    return $url;
                }
            }
        }

        if (typeof tempCdnAllowUrl !== 'undefined') {
            let check = false;
            for (let item of tempCdnAllowUrl) {
                if ($url.includes(item)) {
                    check = true;
                    break;
                }
            }
            if (!check) {
                return $url;
            }
        }

        if (typeof filters !== 'undefined' && typeof filters.zoomIn !== 'undefined') {
            zoomIn = filters.zoomIn;
        }

        if ($url.substr(0, 4) == 'http') {
            $url = $url.replace('https://', '');
            $url = $url.replace('http://', '');
        }
        if ($url.includes('redbubble.net')) {
            $url = 'asset/' + this.crypt('megaads', $url);
        }
        if ($url.includes('i.etsystatic.com') || $url.includes('res.cloudinary.com')) {
            $url = 'asset/' + this.crypt('megaads', $url);
        }
        if ($url.includes('?')) {
            $url = encodeURIComponent($url);
        }

        let $baseCdnUrl = this.baseCdnUrl + "/";
        if (zoomIn !== '') {
            $baseCdnUrl = this.baseCdnUrl + "" + zoomIn + "/";
        }

        $fitIn = ($fitIn && $width && $height);

        if ($fitIn) {
            $baseCdnUrl += "fit-in/";
        }

        if ($width || $height) {
            $baseCdnUrl += $width + "x" + $height + "/";
        }

        $baseCdnUrl += $url;

        return $baseCdnUrl;
    }

    private replaceImageUrl = (url: string): string => {
        const cdnReplaceUrl: Record<string, string> = {
            // Add your URL replacement mappings here
        };
        // @ts-ignore
        for (const [key, value] of Object.entries(cdnReplaceUrl)) {
            url = url.replace(key, value);
        }

        return url;
    }

    private crypt = (salt: string, text: string) => {
        const textToChars = (text: string) => text.split("").map((c) => c.charCodeAt(0));
        const byteHex = (n: number) => ("0" + Number(n).toString(16)).substr(-2);
        const applySaltToChar = (code: any) => textToChars(salt).reduce((a, b) => a ^ b, code);

        return text
            .split("")
            .map(textToChars)
            .map(applySaltToChar)
            .map(byteHex)
            .join("");
    };

    private decrypt = (salt: string, encoded: any) => {
        const textToChars = (text: string) => text.split("").map((c) => c.charCodeAt(0));
        const applySaltToChar = (code: any) => textToChars(salt).reduce((a, b) => a ^ b, code);
        return encoded
            .match(/.{1,2}/g)
            .map((hex: any) => parseInt(hex, 16))
            .map(applySaltToChar)
            .map((charCode: any) => String.fromCharCode(charCode))
            .join("");
    };
}

export default Images;