import { Output } from './output.js';
import { join } from '../util/path.js';
export const RESOURCE_CACHE_RESOLUTION_MULTIPLIER = 2;
export class Resource {
    constructor() {
        this.cache = new Map();
        this.default = '';
        this.categories = {};
        this.all = [];
        this.allCategorised = [];
    }
    addCategory(id, label) {
        if (this.categories[id]) {
            console.warn('Category already exists');
            return;
        }
        this.categories[id] = { id, label, resources: {} };
    }
    add(category, id, label, path) {
        if (!this.categories[category]) {
            console.warn('Category does not exist');
            return;
        }
        if (this.categories[category].resources[id]) {
            console.warn('A sticker with this name has already been created');
            return;
        }
        this.categories[category].resources[id] = { id, label, path: path };
    }
    setDefault(id) {
        this.default = id;
    }
    resolve(path) {
        const ASSET_URL_PREFIX_KEY = 'sticker:base-url';
        const prefix = Output.config.get(ASSET_URL_PREFIX_KEY, '/assets/part/stickers');
        return encodeURI(join(prefix, path));
    }
    get resourceSet() {
        if (this.all.length > 0) {
            return this.all;
        }
        Object.keys(this.categories).forEach(category => {
            Object.keys(this.categories[category].resources).forEach(sticker => {
                this.all.push(this.categories[category].resources[sticker]);
            });
        });
        return this.all;
    }
    get categorisedResource() {
        if (this.allCategorised.length > 0) {
            return this.allCategorised;
        }
        Object.keys(this.categories).forEach(category => {
            let categoryObject = {
                id: this.categories[category].id,
                label: this.categories[category].label,
                resources: [],
            };
            Object.keys(this.categories[category].resources).forEach(sticker => {
                const stickerObject = { id: sticker, src: this.getUrl(sticker) };
                categoryObject.resources.push(stickerObject);
            });
            this.allCategorised.push(categoryObject);
        });
        return this.allCategorised;
    }
    get categoryEnum() {
        return Object.keys(this.categories).map(category => [this.categories[category].label, this.categories[category].id]);
    }
    cacheValue(id, type = 'image') {
        if (type !== 'image') {
            console.warn('cached item type not recognised');
            return;
        }
        return this.cache.get(id);
    }
    rasteriseImage(img) {
        const canvas = document.createElement('canvas');
        canvas.width = img.width * RESOURCE_CACHE_RESOLUTION_MULTIPLIER;
        canvas.height = img.height * RESOURCE_CACHE_RESOLUTION_MULTIPLIER;
        const ctx = canvas.getContext('2d');
        if (ctx) {
            ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
        }
        return canvas;
    }
    load(resource) {
        return new Promise((resolve, reject) => {
            const img = new Image();
            const started = Date.now();
            img.crossOrigin = "Anonymous";
            const onLoad = () => {
                this.cache.set(resource.id, this.rasteriseImage(img));
                resolve();
                img.removeEventListener('load', onLoad);
                img.removeEventListener('error', onError);
            };
            const onError = () => {
                reject();
                img.removeEventListener('load', onLoad);
                img.removeEventListener('error', onError);
            };
            img.addEventListener('load', onLoad);
            img.addEventListener('error', onError);
            img.src = this.resolve(resource.path);
        });
    }
    getRandom() {
        return this.resourceSet[Math.floor(Math.random() * this.resourceSet.length)].id;
    }
    getRandomFrom(id) {
        if (!this.categories[id]) {
            console.warn('Category does not exist');
            return this.default;
        }
        else {
            const randomKey = Object.keys(this.categories[id].resources)[Math.floor(Math.random() * Object.keys(this.categories[id].resources).length)];
            return this.categories[id].resources[randomKey].id;
        }
    }
    getUrl(id) {
        if (!id) {
            console.warn(`No sticker provided`);
            return '';
        }
        let selectedSticker = this.resourceSet.find(sticker => sticker.id === id);
        if (!selectedSticker) {
            selectedSticker = this.resourceSet.find(sticker => sticker.id === this.default);
        }
        if (!selectedSticker) {
            console.warn(`Sticker ${id} does not exist`);
            return '';
        }
        return this.resolve(selectedSticker.path);
    }
    getLabel(id) {
        const selectedSticker = this.resourceSet.find(sticker => sticker.id === id);
        if (!selectedSticker) {
            console.warn('Sticker does not exist');
            return;
        }
        return this.resolve(selectedSticker.label);
    }
}
export class Resources {
    constructor() {
        this.resources = new Map();
        this.resources.set('stickers', new Resource());
    }
    get(id) {
        return this.resources.get(id);
    }
    load(progress) {
        let total = 0;
        this.resources.forEach((resource) => {
            total += resource.resourceSet.length;
        });
        let completed = 0;
        const promises = [];
        this.resources.forEach((resource) => {
            resource.resourceSet.forEach((r) => {
                const p = resource.load(r)
                    .then(() => {
                    completed += 1;
                    progress(completed / total);
                }).catch(() => {
                    /* Report progress even for failed images */
                    completed += 1;
                    progress(completed / total);
                });
                promises.push(p);
            });
        });
        return Promise.all(promises);
    }
}
//# sourceMappingURL=resources.js.map