Source: ui/base/abstract-alert.js

/**
 * @module ui/alert.reel
 */
var Component = require("../component").Component,
    ModalOverlay = require("../modal-overlay.reel").ModalOverlay,
    Promise = require("../../core/promise").Promise;

/**
 * @class Alert
 * @extends Component
 */
exports.AbstractAlert = Component.specialize(/** @lends AbstractAlert# */ {
    constructor: {
        value: function AbstractAlert() {
            if (this.constructor === AbstractAlert) {
                throw new Error("AbstractAlert cannot be instantiated.");
            }
        }
    },

    /**
     * This property should point to the overlay component.
     */
    _overlay: {
        value: null
    },

    /**
     * This property should point to the "OK" "action" component.
     */
    _okButton: {
        value: null
    },

    _userActionPromise: {
        value: null
    },

    title: {
        value: "Alert"
    },

    okLabel: {
        value: "OK"
    },

    message: {
        value: null
    },

    enterDocument: {
        value: function (firstTime) {
            var constructor;

            if (firstTime) {
                // If the instance entering the document is the singleton of
                // its constructor then we need to resolve the promise to start
                // the chain of messages that might be pending.
                constructor = Object.getPrototypeOf(this).constructor;
                if (this === constructor._instance) {
                    constructor._nextMessagePromiseHandlerResolve();
                }
                this._okButton.addEventListener("action", this, false);
            }
        }
    },
    
    resolveUserAction: {
        value: null
    },
    rejectUserAction: {
        value: null
    },

    /**
     * Returns a promise for the close of the alert
     */
    show: {
        value: function() {
            if (!this._userActionPromise) {
                this._overlay.hasModalMask = false;
                this._overlay.show();
                var self = this;
                this._userActionPromise = new Promise(function(resolve, reject) {
                    self.resolveUserAction = resolve;
                    self.rejectUserAction = reject;
                });
            }

            return this._userActionPromise;
        }
    },

    handleAction: {
        value: function (event) {
            if (event.target === this._okButton) {
                this.resolveUserAction();
                this._userActionPromise = null;
                this._overlay.hide();
            }
        }
    }
}, {
    _instance: {
        value: null
    },

    /**
     * This promise is initially the promise at _nextMessagePromise and is
     * resolved at enterDocument time, this is when the overlay is available.
     
     * Implemented with a getter to ensure that this property is not initialized
     * on the AbstractAlert but on the type that extends it.
     
     */
     _nextMessagePromiseHandlerResolve: {
         value: null
     },
     _nextMessagePromiseHandlerReject: {
         value: null
     },
    __nextMessagePromise: {
        value: null
    },

    _nextMessagePromise: {
        set: function (value) {
            this.__nextMessagePromise = value;
        },
        get: function () {
            if (!this.hasOwnProperty("__nextMessagePromise")) {
                var self = this;
                this.__nextMessagePromise = new Promise(function(resolve, reject) {
                     self._nextMessagePromiseHandlerResolve = resolve;
                     self._nextMessagePromiseHandlerReject = reject;
                 });
            }

            return this.__nextMessagePromise;
        }
    },

    _setupInstance: {
        value: function () {
            var instance;

            instance = this._instance = new this();
            // HACK: outside of the draw cycle, no other way to do it at the
            // moment we need the DrawManager to solve this problem.
            instance.element = instance.rootComponent.element.createElement("div");
            instance.element.ownerDocument.body.appendChild(instance.element);
            instance.attachToParentComponent();

            instance.needsDraw = true;
        }
    },

    show: {
        value: function (message, title) {
            var instance,
                self = this;

            if (!this.hasOwnProperty("_instance")) {
                this._setupInstance();
            }

            instance = this._instance;

            this._nextMessagePromise = this._nextMessagePromise.then(function () {
                if (title) {
                    instance.title = title;
                } else {
                    instance.title = self.prototype.title;
                }
                instance.message = message;

                return instance.show();
            });

            return this._nextMessagePromise;
        }
    }
});