/*
* Copyright (C) 2015-2016 by Arena of Titans Contributors.
*
* This file is part of Arena of Titans.
*
* Arena of Titans is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Arena of Titans is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Arena of Titans. If not, see <http://www.gnu.org/licenses/>.
*/

import { inject } from 'aurelia-framework';
import { EventAggregatorSubscriptions, Wait } from '../../services/utils';


@inject(EventAggregatorSubscriptions)
export class Popup {
    _popupDefered;

    constructor(eas) {
        this._eas = eas;
    }

    display(type, data, {timeout = 0} = {}) {
        let popupDefered = {};
        popupDefered.promise = new Promise((resolve, reject) => {
            popupDefered.resolve = resolve;
            popupDefered.reject = reject;
        });

        if (timeout) {
            let closeTimeout = setTimeout(() => {
                popupDefered.resolve();
            }, timeout);
            let cancelCloseTimout = () => {
                clearTimeout(closeTimeout);
            };
            popupDefered.promise.then(cancelCloseTimout, cancelCloseTimout);
        }

        let startCounter = () => {
            this._eas.publish('aot:game:counter_start');
        };
        popupDefered.promise.then(startCounter, startCounter);

        this._eas.publish('aot:popup:display', {
            type: type,
            data: data,
            defered: popupDefered,
        });

        return popupDefered.promise;
    }
}


@inject(Element, EventAggregatorSubscriptions)
export class AotPopupCustomElement {
    data = null;
    type = null;
    defered = null;

    background = '';

    constructor(element, eas) {
        this._element = element;
        this._eas = eas;

        this._eas.subscribe('aot:popup:display', message => {
            this.data = message.data;
            this.type = message.type;
            this.defered = message.defered;

            this._open();

            this.defered.promise.then(() => {
                this._close();
            }, () => {
                this._close();
            });
        });
    }

    _open() {
        switch (this.type) {
            case 'game-over':
                this.background = 'game-over';
                break;
            case 'player-box':
                this.background = 'popup-player-box';
                break;
            case 'transition':
                this.background = 'popup-transition';
                break;
            default:
                this.background = 'default';
                break;
        }

        Wait.forClass('popup-container', {
            element: this._element,
            fresh: true,
        }).then(elements => elements[0].focus());
    }

    _close() {
        this.data = null;
        this.type = null;
        this.defered = null;
    }

    bind() {
        this._keyupEventListener = event => {
            let keyCode = event.code.toLowerCase();

            // The player must validate the game over popup
            if ((keyCode === 'escape' || keyCode === 'esc') && this.type !== 'game-over') {
                this.defered.reject();
            }
        };
        window.addEventListener('keyup', event => {
            this._keyupEventListener(event);
        });
    }

    unbind() {
        window.removeEventListener('keyup', this._keyupEventListener);
        this._eas.dispose();
    }
}

@@ -956,23 +956,45 @@
   _popup
-Defered
+s;%0A    _displayedPopupPromise
 ;%0A%0A    c
@@ -1035,16 +1035,88 @@
 s = eas;
+%0A%0A        this._popups = %5B%5D;%0A        this._displayedPopupPromise = null;
 %0A    %7D%0A%0A
@@ -1361,337 +1361,8 @@
 );%0A%0A
-        if (timeout) %7B%0A            let closeTimeout = setTimeout(() =%3E %7B%0A                popupDefered.resolve();%0A            %7D, timeout);%0A            let cancelCloseTimout = () =%3E %7B%0A                clearTimeout(closeTimeout);%0A            %7D;%0A            popupDefered.promise.then(cancelCloseTimout, cancelCloseTimout);%0A        %7D%0A%0A
     
@@ -1542,41 +1542,20 @@
 is._
-eas.publish('aot:popup:display', 
+popups.push(
 %7B%0A  
@@ -1647,49 +1647,1387 @@
     
-%7D);%0A%0A        return popupDefered.promise;
+    timeout: timeout,%0A        %7D);%0A        this._displayNext();%0A%0A        return popupDefered.promise;%0A    %7D%0A%0A    _displayNext() %7B%0A        // We check that we have popup to display: if we are in the recursion, this._popups%0A        // may be an empty array.%0A        if (this._displayedPopupPromise === null && this._popups.length %3E 0) %7B%0A            let popup = this._popups.shift();%0A%0A            if (popup.timeout) %7B%0A                let closeTimeout = setTimeout(() =%3E %7B%0A                    popup.defered.resolve();%0A                %7D, popup.timeout);%0A                let cancelCloseTimout = () =%3E %7B%0A                    clearTimeout(closeTimeout);%0A                %7D;%0A                popup.defered.promise.then(cancelCloseTimout, cancelCloseTimout);%0A            %7D%0A%0A            this._eas.publish('aot:popup:display', %7B%0A                type: popup.type,%0A                data: popup.data,%0A                defered: popup.defered,%0A            %7D);%0A%0A            this._displayedPopupPromise = popup.defered.promise;%0A        %7D else %7B%0A            // As soon as the current popup is closed, we display the next one.%0A            this._displayedPopupPromise.then(() =%3E %7B%0A                this._displayedPopupPromise = null;%0A                this._displayNext();%0A            %7D, () =%3E %7B%0A                this._displayedPopupPromise = null;%0A                this._displayNext();%0A            %7D);%0A        %7D
 %0A   

manage a stack of popup to display multiple popups sequentially