import settings from '../config/settings';
import internalEvents from '../events/internalEvents';
import { PointsWidgetConfig } from '../models/views/pointswidgetconfig';
import nonstop from '../nonstop';
import connectService from '../services/connectService';
import eventEmitter from '../services/eventEmitter';
import { PresentableView } from './abstract/presentableView';
import html from './pointsWidget.html';

export class PointsWidget extends PresentableView {

    public static updateAll() {
        eventEmitter.broadcastEvent(internalEvents.UpdatePointsWidgets);
    }

    protected logTag: string = 'PointsWidget';

    private limitReachedMessageShown: boolean = false;

    constructor(private inElement: HTMLElement, private config: PointsWidgetConfig) {
        super();
        config.isLeftRounded = config.isLeftRounded !== undefined ? config.isLeftRounded : true;
        config.isRightRounded = config.isRightRounded !== undefined ? config.isRightRounded : true;
        config.dropdownEnabled = config.dropdownEnabled !== undefined ? config.dropdownEnabled : true;
    }

    public presentSelf(): Promise<boolean> {
        return new Promise<boolean>((resolve, reject) => {
            if (!connectService.isConnected) {
                this.logError('Presenting a points widget requires a current user. Please call Nonstop.default.login first.');
                reject(false);
            } else if (this.inElement === undefined) {
                this.logError('Presenting a points widget requires a valid input element. Please ensure the element you are passing exists.');
                reject(false);
            } else {
                this.renderView();
                resolve(true);
            }
        });
    }

    private configureViewProperties(template: string): string {
        if (connectService.currentUser) {
            template = template.replace(/{{currentPointsTotal}}/gi, connectService.currentUser.totalPointsDisplay);
        } else {
            template = '';
        }
        if (connectService.hasExceededPointsLimit) {
            template = template.replace(/{{limitMessage}}/gi, connectService.pointsLimitMessage);
        } else {
            template = template.replace(/{{limitMessage}}/gi, '');
        }
        return template;
    }

    private configureViewEvents(pointsWidgetElem: HTMLElement) {
        eventEmitter.on(internalEvents.UpdatePointsWidgets, () => {
            this.updateView(pointsWidgetElem);
        });
        pointsWidgetElem.addEventListener('click', () => {
            eventEmitter.broadcastEvent(nonstop.Events.GoToNonstopHome, null, this.inElement);
        });
    }

    private renderView() {
        const injectedElem = document.createElement('div');
        injectedElem.innerHTML = this.configureViewProperties(html);
        this.inElement.appendChild(injectedElem);
        this.updateView(injectedElem);
        this.configureViewEvents(injectedElem);
    }

    private updateView(pointsWidgetElem: HTMLElement) {
        const widget = pointsWidgetElem.querySelectorAll('.ns-points-widget-container')[0];
        if (this.config.isLeftRounded) {
            widget.classList.add('ns-rounded-left');
        }
        if (this.config.isRightRounded) {
            widget.classList.add('ns-rounded-right');
        }

        if (connectService.currentUser) {
            const pointsTotal = pointsWidgetElem.querySelectorAll('.ns-points-total span')[0];
            pointsTotal.innerHTML = connectService.currentUser.totalPointsDisplay;
        }
        if (connectService.hasExceededPointsLimit && !this.limitReachedMessageShown && this.config.dropdownEnabled) {
            this.limitReachedMessageShown = true;
            const pointsWidget = pointsWidgetElem.querySelectorAll('.ns-points-widget')[0];
            pointsWidget.classList.add('ns-fill-yellow');
            const pointsMessage = pointsWidgetElem.querySelectorAll('.ns-points-message')[0];
            pointsMessage.classList.remove('ns-hide');
            pointsMessage.classList.add('animated');
            pointsMessage.classList.add('fadeIn');
            pointsMessage.innerHTML = connectService.pointsLimitMessage;
            setTimeout(() => {
                pointsMessage.classList.remove('fadeIn');
                pointsMessage.classList.add('fadeOut');
                setTimeout(() => {
                    pointsMessage.classList.remove('animated');
                    pointsMessage.classList.remove('fadeOut');
                    pointsMessage.classList.add('ns-hide');
                }, settings.animateCssAnimationDurationMs);
            }, settings.animateCssAnimationDurationMs + (3 * settings.animateCssAnimationDurationMs));
        }
    }
}