
Engine.DialogManagerStatics = {};
Engine.DialogManagerStatics.UseLayer = { "Dialogs":1, "Tutorial":2, "Over":3 };
Engine.DialogManagerStatics.TransitionType = { "Shown":1, "Hidden":2 };

Engine.DialogManager = class 
{
    constructor()
    {

        this.dialogsLayer = new Engine.DialogLayer("DialogLayer");
        this.dialogsOverLayer = new Engine.DialogLayer("DialogOverLayer");

        this.UILayer = null;

        this.dialogs = [];
        this.dialogsToUpdate = [];

        this.TutorialLayer = null;
        this.OverLayer = null;

        this.activeDialogsChanged = new Action();
        this.dialogTransitioned = new Action();
        this.dialogAvailableChanged = new Action();
        this.lastDialogWasClosed = new Action();
        this.dialogOpenOrClosed = new Action();
    }

    hideAllActiveDialogs()
    {
        for(var i = 0; i < this.dialogs.length; i++)
        {
            if (this.dialogs[i].active) this.dialogs[i].hide(true);
        }
    }

    get activeDialogCount()
    {
        var count = 0;
        for(var i = 0; i < this.dialogs.length; i++) if (this.dialogs[i].active) count++;
        return count;
    }
    
    getTopDialog()
    {
        var top = this.dialogsOverLayer.getTopDialog();
        if (top == null) top = this.dialogsLayer.getTopDialog();
        return top;
    }    

    enable()
    {
        Engine.EnterFrameManagerInstance.add(this, (timeElapsed) => { this.update(timeElapsed); });
    }

    disable()
    {
        Engine.EnterFrameManagerInstance.remove(this);
    }

    getUILayer() { return this.UILayer; }
    getTutorialLayer() { return this.TutorialLayer; }

    get activeBlockers() { return this.dialogsLayer.activeBlockers + this.dialogsOverLayer.activeBlockers; }

    //------- Events -------
    fireActiveDialogsChanged() { if (this.activeDialogsChanged != null) this.activeDialogsChanged.call(); }
    fireDialogTransitioned(dialogClassName, transition) { if (this.dialogTransitioned != null) this.dialogTransitioned.call(dialogClassName, transition); }
    fireDialogAvailableChanged(lastDialog) { if (this.dialogAvailableChanged != null) this.dialogAvailableChanged.call(lastDialog); }
    fireLastDialogWasClosed() { if (this.lastDialogWasClosed != null) this.lastDialogWasClosed.call(); }
    fireDialogOpenOrClosed(dialog, type) { if (this.dialogOpenOrClosed != null) this.dialogOpenOrClosed.call(dialog, type); }

    updateBlockers()
    {
        this.dialogsLayer.updateBlockers();
        this.dialogsOverLayer.updateBlockers();
    }


    resolutionChanged(width, height)
    {
        this.dialogsLayer.resolutionChanged(width, height);
        this.dialogsOverLayer.resolutionChanged(width, height);

        for (var i = 0; i < this.dialogs.length; i++)
        {
            if (this.dialogs[i].active) this.dialogs[i].resolutionChanged(width, height);
        }
    }

    addDialogToUpdate(dialog)
    {
        if (this.dialogsToUpdate.indexOf(dialog) == -1) this.dialogsToUpdate.push(dialog);
    }

    update(timeElapsed)
    {
        var numToUpdate = this.dialogsToUpdate.length;
        for (var i = 0; i < this.dialogsToUpdate.length; i++)
        {
            if (this.dialogsToUpdate[i].Active == false)
            {
                this.dialogsToUpdate.splice(i, 1);
                i--;
            }
        }

        for (var i = 0; i < this.dialogsToUpdate.length; i++)
        {
            if (this.dialogsToUpdate[i].active)
            {
                this.dialogsToUpdate[i].update(timeElapsed);
            }
        }
    }

    setUILayer(uiLayer)
    {
        this.UILayer = uiLayer;
        this.UILayer.addChild(this.dialogsLayer);
    }

    
    setTutorialLayer(tutorialLayer)
    {
        this.TutorialLayer = tutorialLayer;
    }

    setOverLayer(overLayer)
    {
        this.OverLayer = overLayer;
        this.OverLayer.addChild(this.dialogsOverLayer);
    }

    get activeDialogs()
    { 
        var activeDialogs = [];
        for (var i = 0; i < this.dialogs.length; i++) if (this.dialogs[i].active) activeDialogs.push(this.dialogs[i]);
        return activeDialogs;
    }

    showMessageBox(message, okText, closeText, callbackFunction, width, height, overLayer)
    {
        if (callbackFunction === undefined) callbackFunction = null;
        if (width === undefined) width = null;
        if (height === undefined) height = null;
        if (overLayer === undefined) overLayer = false;
        
        var dialog = this.getDialog(Engine.MessageBox, overLayer ? Engine.DialogManagerStatics.UseLayer.Over : Engine.DialogManagerStatics.UseLayer.Dialogs);
        dialog.show(message, okText, closeText, callbackFunction, width, height);

        return dialog;
    }

    showGraphicViewer(callbackFunction)
    {
        if (callbackFunction === undefined) callbackFunction = null;
        
        var dialog = this.getDialog(GraphicViewer);
        dialog.show(callbackFunction);

        return dialog;
    }
	
    showLoadingTextBox(message, delay, initialTransparent, alwaysTransparent)
    {
        if (!delay) delay = 0;
        if (!initialTransparent) initialTransparent = false;
        if (!alwaysTransparent) alwaysTransparent = false;

        var dialog = this.getDialog(Engine.LoadingTextBox);
        dialog.show(message, delay, initialTransparent, alwaysTransparent);
        return dialog;
    }

    showErrorBox(message, time)
    {
        if (!time) time = 1;
        var dialog = this.getDialog(Engine.ErrorBox);
        dialog.show(message, time);
        return dialog;
    }


    /* Get Dialog takes the Class of the dialog you require 
    and returns you an available dialog from the pool */
    getDialog(classConstructor, layer)
    {
        if (layer === undefined) layer = Engine.DialogManagerStatics.UseLayer.Dialogs;

        var dialog = this.getAvailableDialog(classConstructor, false, layer);
        if (dialog != null) return dialog;

        var parentClip = null;
        switch (layer)
        {
            case Engine.DialogManagerStatics.UseLayer.Dialogs:
                parentClip = this.dialogsLayer;
                break;
            case Engine.DialogManagerStatics.UseLayer.Tutorial:
                parentClip = this.TutorialLayer;
                break;
            case Engine.DialogManagerStatics.UseLayer.Over:
                parentClip = this.dialogsOverLayer;
                break;
        }
        
        if (classConstructor === undefined){
            Debug.Log("Constructor null?!");
        }
        dialog = new classConstructor(parentClip);
        this.dialogs.push(dialog);

        return dialog;
    }
    
    getNumActiveDialogs()
    {
        return this.activeDialogs.length;
    }

    getAllActiveDialogs(classConstructor)
    {
        var activeDialog = [];//new List<Dialog>();
        for (var i = 0; i < this.dialogs.length; i++)
        {
            if (this.dialogs[i] instanceof classConstructor && this.dialogs[i].active == true)
            {
                activeDialog.push(this.dialogs[i]);
            }
        }
        return activeDialog;
    }

    getActiveDialog(classConstructor, layer)
    {
        if (!layer) layer = Engine.DialogManagerStatics.UseLayer.Dialogs;
        return this.getAvailableDialog(classConstructor, true, layer);
    }

    getAvailableDialog(classConstructor, active, layer = Engine.DialogManagerStatics.UseLayer.Dialogs)
    {
        if (!layer) layer = Engine.DialogManagerStatics.UseLayer.Dialogs;

        var parentClip = null;
        switch (layer)
        {
            case Engine.DialogManagerStatics.UseLayer.Dialogs:
                parentClip = this.dialogsLayer;
                break;
            case Engine.DialogManagerStatics.UseLayer.Tutorial:
                parentClip = this.TutorialLayer;
                break;
            case Engine.DialogManagerStatics.UseLayer.Over:
                parentClip = this.dialogsOverLayer;
                break;
        }

        for (var i = 0; i < this.dialogs.length; i++)
        {
			var matches = false;
			if (typeof classConstructor == "string")
			{
				matches = this.dialogs[i].constructor.name == classConstructor;
			}
			else
			{
				matches = this.dialogs[i] instanceof classConstructor;
			}
            
            if (matches && this.dialogs[i].active == active && this.dialogs[i].parentClip == parentClip)
            {
                return this.dialogs[i];
            }
        }

        return null;
    }

}
