// ax5.ui.toast
(function () {

    var UI = ax5.ui;
    var U = ax5.util;
    var TOAST;

    UI.addClass({
        className: "toast"
    }, (function () {
        /**
         * @class ax5toast
         * @classdesc
         * @author tom@axisj.com
         * @example
         * ```
         * ```js
         * var toast = new ax5.ui.toast();
         * toast.setConfig({
         *     icon: '<i class="fa fa-bug"></i>',
         *     containerPosition: "bottom-right",
         *     closeIcon: '<i class="fa fa-times"></i>'
         * });
         *
         * toast.onStateChanged = function(){
         *     console.log(this);
         * };
         *
         * toast.push({
         *     icon: '<i class="fa fa-book"></i>',
         *     msg:"999999"
         * });
         *
         * toast.push({
         *     theme: theme,
         *     msg: 'toast message'
         * });
         * ```
         */
        var ax5toast = function () {
            var
                self = this,
                cfg,
                toastSeq = 0, toastSeqClear = null;

            this.instanceId = ax5.getGuid();
            this.config = {
                clickEventName: "click", //(('ontouchstart' in document.documentElement) ? "touchstart" : "click"),
                theme: 'default',
                width: 300,
                icon: '',
                closeIcon: '',
                msg: '',
                lang: {
                    "ok": "ok", "cancel": "cancel"
                },
                displayTime: 3000,
                animateTime: 250,
                containerPosition: "bottom-left"
            };
            this.toastContainer = null;
            this.queue = [];

            cfg = this.config;

            var
                onStateChanged = function (opts, that) {
                    if (opts && opts.onStateChanged) {
                        opts.onStateChanged.call(that, that);
                    }
                    else if (this.onStateChanged) {
                        this.onStateChanged.call(that, that);
                    }

                    opts = null;
                    that = null;
                    return true;
                },
                /**
                 * @method ax5toast.getContent
                 * @param {String} toastId
                 * @param {Object} opts
                 * @returns toastDisplay
                 * @example
                 * ```js
                 * ax5toast.getContent('ax5-toast-3-1', opts);
                 * ```
                 */
                getContent = function (toastId, opts) {

                    var
                        data = {
                            toastId: toastId,
                            theme: opts.theme,
                            icon: opts.icon,
                            msg: (opts.msg || "").replace(/\n/g, "<br/>"),
                            btns: opts.btns,
                            closeIcon: opts.closeIcon
                        };

                    try {
                        return TOAST.tmpl.get.call(this, "toastDisplay", data);
                    }
                    finally {
                        toastId = null;
                        data = null;
                    }
                },
                /**
                 * @method ax5toast.open
                 * @param opts
                 * @param callBack
                 * @returns {ax5toast}
                 */
                open = function (opts, callBack) {
                    if (toastSeqClear) clearTimeout(toastSeqClear);

                    var
                        toastBox,
                        box = {
                            width: opts.width
                        };

                    opts.id = 'ax5-toast-' + self.containerId + '-' + (++toastSeq);
                    if (jQuery('#' + opts.id).get(0)) return this;

                    if (U.left(cfg.containerPosition, '-') == 'bottom') {
                        this.toastContainer.append(getContent(opts.id, opts));
                    }
                    else {
                        this.toastContainer.prepend(getContent(opts.id, opts));
                    }

                    toastBox = jQuery('#' + opts.id);
                    toastBox.css({width: box.width});
                    opts.toastBox = toastBox;
                    this.queue.push(opts);

                    onStateChanged.call(this, opts, {
                        self: this,
                        state: "open",
                        toastId: opts.id
                    });

                    if (opts.toastType === "push") {
                        // 자동 제거 타이머 시작
                        setTimeout((function () {
                            this.close(opts, callBack);
                        }).bind(this), cfg.displayTime);

                        toastBox.find("[data-ax-toast-btn]").on(cfg.clickEventName, (function (e) {
                            btnOnClick.call(this, e || window.event, opts, toastBox, callBack);
                        }).bind(this));
                    }
                    else if (opts.toastType === "confirm") {
                        toastBox.find("[data-ax-toast-btn]").on(cfg.clickEventName, (function (e) {
                            btnOnClick.call(this, e || window.event, opts, toastBox, callBack);
                        }).bind(this));
                    }

                    box = null;
                },
                btnOnClick = function (e, opts, toastBox, callBack, target, k) {
                    target = U.findParentNode(e.target, function (target) {
                        if (target.getAttribute("data-ax-toast-btn")) {
                            return true;
                        }
                    });

                    if (target) {
                        k = target.getAttribute("data-ax-toast-btn");

                        var that = {
                            key: k, value: (opts.btns) ? opts.btns[k] : k,
                            toastId: opts.id,
                            btn_target: target
                        };

                        if (opts.btns && opts.btns[k].onClick) {
                            opts.btns[k].onClick.call(that, k);
                        }
                        else if (opts.toastType === "push") {
                            if (callBack) callBack.call(that, k);
                            this.close(opts, callBack);
                        }
                        else if (opts.toastType === "confirm") {
                            if (callBack) callBack.call(that, k);
                            this.close(opts, callBack);
                        }
                    }

                    e = null;
                    opts = null;
                    toastBox = null;
                    callBack = null;
                    target = null;
                    k = null;
                };

            /**
             * Preferences of toast UI
             * @method ax5toast.set_config
             * @param {Object} config - 클래스 속성값
             * @returns {ax5toast}
             * @example
             * ```
             * ```
             */
            //== class body start
            this.init = function () {
                this.onStateChanged = cfg.onStateChanged;
                // after set_config();
                self.containerId = ax5.getGuid();
                var styles = [];
                if (cfg.zIndex) {
                    styles.push("z-index:" + cfg.zIndex);
                }
                jQuery(document.body).append('<div class="ax5-ui-toast-container ' + cfg.containerPosition + '" data-toast-container="' +
                    '' + self.containerId + '" style="' + styles.join(";") + '"></div>');
                this.toastContainer = jQuery('[data-toast-container="' + self.containerId + '"]');
            };

            /**
             * @method ax5toast.push
             * @param opts
             * @param callBack
             * @returns {ax5toast}
             */
            this.push = function (opts, callBack) {
                if (!self.containerId) {
                    this.init();
                }
                if (U.isString(opts)) {
                    opts = {
                        title: cfg.title,
                        msg: opts
                    }
                }
                opts.toastType = "push";

                self.dialogConfig = {};
                jQuery.extend(true, self.dialogConfig, cfg, opts);
                opts = self.dialogConfig;

                open.call(this, opts, callBack);

                opts = null;
                callBack = null;
                return this;
            };

            /**
             * @method ax5toast.confirm
             * @param opts
             * @param callBack
             * @returns {ax5toast}
             */
            this.confirm = function (opts, callBack) {
                if (!self.containerId) {
                    this.init();
                }
                if (U.isString(opts)) {
                    opts = {
                        title: cfg.title,
                        msg: opts
                    }
                }
                opts.toastType = "confirm";

                self.dialogConfig = {};
                jQuery.extend(true, self.dialogConfig, cfg, opts);
                opts = self.dialogConfig;

                if (typeof opts.btns === "undefined") {
                    opts.btns = {
                        ok: {label: cfg.lang["ok"], theme: opts.theme}
                    };
                }
                open.call(this, opts, callBack);

                opts = null;
                callBack = null;
                return this;
            };

            /**
             * close the toast
             * @method ax5toast.close
             * @returns {ax5toast}
             * @example
             * ```
             * my_toast.close();
             * ```
             */
            this.close = function (opts, callBack) {
                if (typeof opts === "undefined") {
                    opts = U.last(this.queue);
                }

                var toastBox = opts.toastBox;
                toastBox.addClass((opts.toastType == "push") ? "removed" : "destroy");
                this.queue = U.filter(this.queue, function () {
                    return opts.id != this.id;
                });
                setTimeout((function () {
                    var that = {
                        toastId: opts.id
                    };

                    toastBox.remove();
                    if (callBack) callBack.call(that);

                    that = {
                        self: this,
                        state: "close",
                        toastId: opts.id
                    };
                    onStateChanged.call(this, opts, that);

                    // 3초후에도 아무 일이 없다면 완전히 제거
                    if (this.queue.length === 0) {
                        if (toastSeqClear) clearTimeout(toastSeqClear);
                        toastSeqClear = setTimeout((function () {
                            /// console.log("try clear seq");
                            if (this.queue.length === 0) toastSeq = 0;
                        }).bind(this), 3000);
                    }

                    that = null;
                    opts = null;
                    callBack = null;
                    toastBox = null;
                }).bind(this), cfg.animateTime);

                return this;
            };

            // 클래스 생성자
            this.main = (function () {

                UI.toast_instance = UI.toast_instance || [];
                UI.toast_instance.push(this);

                if (arguments && U.isObject(arguments[0])) {
                    this.setConfig(arguments[0]);
                }
            }).apply(this, arguments);
        };
        return ax5toast;
    })());
    TOAST = ax5.ui.toast;
})();