import { h } from '../webmapgl.core.js';

class LikeButton {
    constructor() {
        this.count = 0;
        this.liked = false;
        this.attribute = '_likes';
        this.disabled = false;
        this.iconNo = 'star-outline';
        this.iconYes = 'star';
        this.method = 'POST';
    }
    async componentWillLoad() {
        await this.setState();
    }
    async setState() {
        if (this.feature) {
            this.count = this.feature.properties[this.attribute];
            this.proxy = await this.likeCtrl.create(this.feature);
            this.liked = this.proxy.isLiked();
        }
    }
    async toggle() {
        this.liked = !this.liked;
        this.count += (this.liked) ? 1 : -1;
        if (this.feature && this.feature.properties)
            this.feature.properties[this.attribute] = this.count;
        (this.liked) ? this.proxy.like() : this.proxy.unlike();
        let success = false;
        let clientId = this.proxy.getClientId();
        try {
            await this.restCtrl.create({
                type: 'Feature',
                properties: {
                    action: (this.liked) ? 'like' : 'unlike',
                    feature_id: this.feature.id,
                    client_id: clientId
                }
            }, {
                url: this.url,
                token: this.token,
                method: this.method,
                mode: this.requestMode
            });
            success = true;
        }
        catch (e) { }
        this.glLike.emit({
            success: success,
            feature: this.feature,
            action: (this.liked) ? 'like' : 'unlike',
            client_id: clientId
        });
    }
    render() {
        return (h("ion-button", { fill: "clear", onClick: () => { if (!this.disabled)
                this.toggle(); }, disabled: this.disabled },
            h("ion-icon", { slot: "start", name: (this.liked) ? this.iconYes : this.iconNo }),
            h("span", { class: "gl-like-button-count" }, this.count)));
    }
    static get is() { return "gl-like-button"; }
    static get properties() { return {
        "attribute": {
            "type": String,
            "attr": "attribute"
        },
        "count": {
            "state": true
        },
        "disabled": {
            "type": Boolean,
            "attr": "disabled"
        },
        "el": {
            "elementRef": true
        },
        "feature": {
            "type": "Any",
            "attr": "feature",
            "mutable": true,
            "watchCallbacks": ["setState"]
        },
        "iconNo": {
            "type": String,
            "attr": "icon-no"
        },
        "iconYes": {
            "type": String,
            "attr": "icon-yes"
        },
        "likeCtrl": {
            "connect": "gl-like-controller"
        },
        "liked": {
            "state": true
        },
        "method": {
            "type": String,
            "attr": "method"
        },
        "proxy": {
            "state": true
        },
        "requestMode": {
            "type": String,
            "attr": "request-mode"
        },
        "restCtrl": {
            "connect": "gl-rest-controller"
        },
        "token": {
            "type": String,
            "attr": "token"
        },
        "url": {
            "type": String,
            "attr": "url"
        }
    }; }
    static get events() { return [{
            "name": "glLike",
            "method": "glLike",
            "bubbles": true,
            "cancelable": true,
            "composed": true
        }]; }
}

class LikeProxy {
    constructor(feature, options = {}) {
        this.feature = feature;
        if (!options.keyPrefix)
            options.keyPrefix = 'webmapgl.like';
        if (!options.clientId) {
            options.clientId = localStorage.getItem(options.keyPrefix + '.clientId');
            if (!options.clientId) {
                options.clientId = this.makeId(64);
                localStorage.setItem(options.keyPrefix + '.clientId', options.clientId);
            }
        }
        this.options = options;
    }
    getClientId() {
        return this.options.clientId;
    }
    isLiked() {
        let likes = this.getArray(this.feature.layer);
        return likes.indexOf(this.feature.id) !== -1;
    }
    like() {
        let likes = this.getArray(this.feature.layer);
        if (likes.indexOf(this.feature.id) === -1)
            likes.push(this.feature.id);
        this.setArray(this.feature.layer, likes);
    }
    unlike() {
        let likes = this.getArray(this.feature.layer);
        let idx = likes.indexOf(this.feature.id);
        if (idx !== -1)
            likes.splice(idx, 1);
        this.setArray(this.feature.layer, likes);
    }
    makeId(length) {
        var id = '';
        var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' +
            '0123456789';
        for (let i = 0; i < length; i++)
            id += chars.charAt(Math.floor(Math.random() * chars.length));
        return id;
    }
    getLayerKey(layer) {
        return this.options.keyPrefix + '|' + document.location.pathname + '|' +
            (layer || 'default');
    }
    getArray(layer) {
        let str = localStorage.getItem(this.getLayerKey(layer));
        if (!str)
            return [];
        return str.split(',').map((v) => parseInt(v)).filter((v) => !isNaN(v));
    }
    setArray(layer, values) {
        let str = values.filter((v) => !isNaN(v))
            .map((v) => v.toString()).join(',');
        localStorage.setItem(this.getLayerKey(layer), str);
    }
}

class LikeController {
    async create(feature, options = {}) {
        return new LikeProxy(feature, options);
    }
    static get is() { return "gl-like-controller"; }
    static get properties() { return {
        "create": {
            "method": true
        }
    }; }
}

class RestController {
    async create(feature, options) {
        let headers = {};
        headers['Content-Type'] = 'application/json';
        if (options.token)
            headers['Authorization'] = 'Bearer ' + options.token;
        return await fetch(options.url, {
            body: JSON.stringify(feature),
            headers: headers,
            method: options.method || 'POST',
            mode: options.mode || 'cors'
        });
    }
    static get is() { return "gl-rest-controller"; }
    static get properties() { return {
        "create": {
            "method": true
        }
    }; }
}

export { LikeButton as GlLikeButton, LikeController as GlLikeController, RestController as GlRestController };
