jscape.account = jscape.account || {};

/** @class */
jscape.WebThemeInfo = Class.extend(
    /** @lends {jscape.WebThemeInfo.prototype} */
{
    /** @constructor */
    initialize: function(a, b, c) {
        this.name = a || "";
        this.owner = b || "";
        this.uri = c || "";
    }
});
jscape.WebThemeInfo.fromJSON = function(data) {
    return data ? new jscape.WebThemeInfo(data.name, data.owner, data.uri) : null;
};
/** @class */
jscape.WebThemeData = Class.extend(
    /** @lends {jscape.WebThemeData.prototype} */
{
    /** @constructor */
    initialize: function(name, logo, owner, uri) {
        this.name = name;
        this.encodedLogo = logo;
        this.owner = owner;
        this.uri = uri;
    }
});
jscape.WebThemeData.fromJSON = function(data) {
    return data ? new jscape.WebThemeData(data.name, data.encodedLogo, data.owner, data.uri) : null;
};

/** @class */
jscape.account.UrlBrandingController = jscape.ui.DatagridController.extend(
    /** @lends {jscape.account.UrlBrandingController.prototype} */
{
    /** @constructor */
    initialize: function() {
        this.view = new jscape.account.UrlBrandingView();

        this.addController = new jscape.account.AddUrlBrandingController();
        this.editController = new jscape.account.EditUrlBrandingController();
        this.deleteController = new jscape.account.DeleteUrlBrandingController();

        this._initValidators();
    },

    start: function() {
        this.view.show(this);
    },

    onResume: function() {
        this.view.refresh();
    },

    onRefresh: function(params) {
        params = jscape.Page.requestParameters(params);
        return jscape.API.listWebThemes(params.startIndex, params.count, params.query)
                .then(jscape.Page.datagridFormatter());
    },

    onAddTheme: function() {
        this.addController.start()
                .done($.proxy(this._themeAdded, this));
    },

    onEditTheme: function(theme) {
        this.editController.start(theme)
                .done($.proxy(this._themeEdited, this));
    },

    onDeleteTheme: function(theme) {
        this.deleteController.start(theme)
                .done($.proxy(this._themeDeleted, this, theme));
    },

    _themeAdded: function (theme) {
        this._recordAdded(theme);
    },

    _themeEdited: function (theme) {
        this._recordEdited(theme);
    },

    _themeDeleted: function (themes) {
        this._recordDeleted(themes);
    },

    _initValidators: function () {
        var v = new jscape.Validator();
        v.rule("webtheme_name", $.proxy(this._themeNameValid, this), window.R.string.WEB_THEME_ERROR_BAD_NAME);
        v.rule("webtheme_unique", $.proxy(this._themeNotExists, this), window.R.string.WEB_THEME_ERROR_ALREADY_EXIST);
        v.rule("webtheme_logo", $.proxy(this._logoLoaded, this), window.R.string.WEB_THEME_ERROR_LOAD_LOGO);
    },

    _themeNameValid: function(name) {
        return name != null && /^[a-zA-Z0-9]+$/i.test(name);
    },

    _themeNotExists: function (name) {
        var names = $.map(this.view.getWebThemes(), function (theme) { return theme.name; });
        return $.inArray(name, names) == -1;
    },

    _logoLoaded: function(_, params) {
        return $(params[0]).data("error") == null;
    }
});

/** @class */
jscape.account.UrlBrandingView = jscape.ui.DatagridView.extend(
    /** @lends {jscape.account.UrlBrandingView.prototype} */
{
    selection: null,

    /** @constructor */
    initialize: function() {
        var initializing = true;

        this.fieldset = $("fieldset[name=urlbrandingfields]");

        this.data = $("table[role=grid][aria-label=urlbranding]", this.fieldset);
        this.data.datagrid({
            fit: true,
            fitColumns: true,
            ctrlSelect: true,
            pagination: true,
            search: true,
            remoteSearch: true,
            remoteSort: true,
            sortName: "name",
            idField: "name",
            columns: [[
                {field: "name", title: $("thead th:nth-child(1)", this.data).text(), sortable: true, width: 90},
                {field: "uri", title: $("thead th:nth-child(2)", this.data).text(), searchable: false, width: 110},
                {field: "owner", title: $("thead th:nth-child(3)", this.data).text(), sortable: true, width: 90}
            ]],
            onSelect: $.proxy(this._adjustState, this),
            onUnselect: $.proxy(this._adjustState, this),
            onDblClickRow: $.proxy(this._onClick$EditButton, this),
            loader: $.proxy(this._onLoad$Data, this),
            onBeforeLoad: function () { return !initializing; },
            onLoadSuccess: $.proxy(this._adjustState, this)
        });

        this.addButton = $("a[role=button][name=add]", this.fieldset).linkbutton({onClick: $.proxy(this._onClick$AddButton, this)});
        this.editButton = $("a[role=button][name=edit]", this.fieldset).linkbutton({disabled: true, onClick: $.proxy(this._onClick$EditButton, this)});
        this.deleteButton = $("a[role=button][name=delete]", this.fieldset).linkbutton({disabled: true, onClick: $.proxy(this._onClick$DeleteButton, this)});

        initializing = false;
    },

    getWebThemes: function() {
        return this.getRecords();
    },

    show: function(listener) {
        this.listener = listener || jscape.account.UrlBrandingView.LISTENER;
        this._adjustState();
    },

    _onLoad$Data: function(params, success, error) {
        this.listener.onRefresh(params).done(success).fail(error);
    },

    _onClick$AddButton: function() {
        this.listener.onAddTheme();
    },

    _onClick$EditButton: function() {
        this.listener.onEditTheme(this.selection[0]);
    },

    _onClick$DeleteButton: function() {
        this.listener.onDeleteTheme(this.selection);
    },

    _adjustState: function () {
        this.selection = this.data.datagrid("getSelections");
        this.editButton.linkbutton(this.selection.length == 1 ? "enable" : "disable");
        this.deleteButton.linkbutton(this.selection.length != 0 ? "enable" : "disable");
    }
});
jscape.account.UrlBrandingView.LISTENER = {
    onRefresh: $.noop,
    onAddTheme: $.noop,
    onEditTheme: $.noop,
    onDeleteTheme: $.noop
};

/** @class */
jscape.account.AddUrlBrandingController = Class.extend(
    /** @lends {jscape.account.AddUrlBrandingController.prototype} */
{
    deferred: null,

    start: function() {
        this.deferred = $.Deferred();
        this._setupDialog().show(this);
        return this.deferred.promise();
    },

    onSubmit: function(dialog) {
        var data = this._createData(dialog);
        dialog.destroy();

        jscape.API.addWebTheme(data)
                .done($.proxy(function(info) { this.deferred.resolve(info); this.deferred = null; }, this))
                .fail($.proxy(function() { this.deferred.reject(); this.deferred = null; }, this));
    },


    onCancel: function(dialog) {
        dialog.destroy();
        this.deferred.reject();
        this.deferred = null;
    },

    webThemeUriFor: function (themeName) {
        return themeName && themeName.trim().length
               ? jscape.API.webThemeUri(themeName)
               : $.Deferred().resolve("").promise();
    },

    _createData: function(dialog) {
        return new jscape.WebThemeData(dialog.getName(), dialog.getLogoData());
    },

    _setupDialog: function() {
        return new jscape.account.AddUrlBrandingDialog();
    }
});

/** @class */
jscape.account.EditUrlBrandingController = Class.extend(
    /** @lends {jscape.account.EditUrlBrandingController.prototype} */
{
    deferred: null,

    start: function (theme) {
        this.themeName = theme.name;
        this.themeUri = theme.uri;
        this.deferred = $.Deferred();

        jscape.API.getWebTheme(theme.name)
                .done($.proxy(function(data) { this._setupDialog(data).show(this); }, this))
                .fail($.proxy(function() { this.deferred.reject(); this.deferred = null; }, this));

        return this.deferred.promise();
    },

    onSubmit: function (dialog) {
        var theme = this._createData(dialog);
        dialog.destroy();

        jscape.API.updateWebTheme(this.themeName, theme)
                .done($.proxy(function(info) { this.deferred.resolve(info); this.deferred = null; }, this))
                .fail($.proxy(function() { this.deferred.reject(); this.deferred = null; }, this));
    },

    onCancel: function (dialog) {
        dialog.destroy();
        this.deferred.reject();
        this.deferred = null;
    },

    _createData: function (dialog) {
        return new jscape.WebThemeData(this.themeName, dialog.getLogoData(), this.themeUri);
    },

    _setupDialog: function (theme) {
        var dialog = new jscape.account.EditUrlBrandingDialog();
        if (theme) {
            dialog.setName(theme.name);
            dialog.setLogoData(theme.encodedLogo);
            dialog.setUri(theme.uri || "");
        }
        return dialog;
    }
});

/** @class */
jscape.account.UrlBrandingDialog = Class.extend(
    /** @lends {jscape.account.UrlBrandingDialog.prototype} */
{
    /** @const */
    DATA_URL: {pattern: /data:image\/.*;base64,(.+)/, template: "data:{0};base64,{1}", placeholder: "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"},

    logoData: "",

    /** @constructor */
    initialize: function(dialog) {
        this.dialog = dialog.clone().attr("id", "");
        this.dialog.dialog({
            width: 700, height: "auto",
            modal: true, resizable: false, closable: true, closed: true,
            buttons: [
                {text: window.R.string.DIALOG_BUTTON_OK, handler: $.proxy(this._onSubmit, this)},
                {text: window.R.string.DIALOG_BUTTON_CANCEL, handler: $.proxy(this._onCancel, this)}
            ],
            onClose: $.proxy(function () {if (!this.closing) { this._onCancel(); }}, this)
        }).show();

        this.fieldset = $("fieldset[name=urlbrandingfields]", this.dialog);

        this.logo = $("div[aria-label=logopreview] img", this.fieldset).attr("id", "logo_" + new Date().getTime().toString(36));
        this.logo.on("load", $.proxy(function() {
            this.logo.data("error", null);
            this.logoFile.validatebox("validate");
        }, this));
        this.logo.on("error", $.proxy(function() {
            this.logo.data("error", true);
            this.logoFile.validatebox("validate");
        }, this));
        this.logo.parent().css({width: 400, height: 100, overflow: "auto", border: "1px solid #DEDEDE"});
        this.logo.parent().click($.proxy(function() { this.logoFile.click(); }, this));

        this.logoFile = $("input[name=logo]", this.fieldset)
                .validatebox({required: true, validType: "webtheme_logo['#" + this.logo.attr("id") + "']", missingMessage: window.R.string.WEB_THEME_ERROR_BAD_LOGO})
                .change($.proxy(this._onChange$Logo, this));

        this.uri = $("span[aria-label=themeuri]", this.fieldset);
    },

    show: function (listener) {
        this.listener = listener;
        this.dialog.dialog("center").dialog("open");
        this.fieldset.form("validate");
        this.fieldset.find("input:first").focus();
    },

    hide: function () {
        if (!this._closed()) {
            this.closing = true;
            this.dialog.dialog("close");
            this.fieldset.form("disableValidation");
            this.closing = false;
        }
    },

    destroy: function() {
        this.dialog.dialog("destroy");
    },

    getName: function() {
        return this.themeName;
    },

    setName: function(value) {
        this.themeName = value;
    },

    getLogoData: function () {
        var dataUrl = this.logo.attr("src");
        return dataUrl && dataUrl != this.DATA_URL.placeholder ? dataUrl.replace(this.DATA_URL.pattern, "$1") : "";
    },

    setLogoData: function (data, type) {
        data = data ? data : this.DATA_URL.placeholder;
        this.logo[0].src = this.DATA_URL.pattern.test(data) ? data : this.DATA_URL.template.supplant({0: type || "image/png", 1: data || ""});
    },

    setUri: function(value) {
        this.uri.text(value || "");
    },

    _onSubmit: function () {
        if (this.fieldset.form("validate")) {
            this.hide();
            this.listener.onSubmit(this);
        }
    },

    _onCancel: function () {
        this.hide();
        this.listener.onCancel(this);
    },

    _closed: function () {
        return !!this.dialog.dialog("options").closed;
    },

    _onChange$Logo: function(e) {
        var files = $.grep(e.target.files || [], function (file) { return file && file.type.match("image.*"); });
        if (files.length && window.FileReader) {
            var type = files[0].type;
            var reader = new FileReader();
            reader.onload = $.proxy(function (e) {
                this.setLogoData(e.target.result, type);
                reader.onload = null;
                type = reader = null;
            }, this);
            reader.readAsDataURL(files[0]);
        } else {
            this.setLogoData("");
        }
    }
});

/** @class */
jscape.account.AddUrlBrandingDialog = jscape.account.UrlBrandingDialog.extend(
    /** @lends {jscape.account.AddUrlBrandingDialog.prototype} */
{
    /** @constructor */
    initialize: function() {
        this._super($("#d-urlbranding-add"));

        this.name = $("input[name=name]", this.fieldset).textbox({required: true, validType: ["webtheme_name", "webtheme_unique"], missingMessage: window.R.string.WEB_THEME_ERROR_BAD_NAME, onChange: $.proxy(this._adjustBrandingUri, this), width: "60%"});
    },

    /** @override */
    getName: function() {
        return this.name.textbox("getValue");
    },

    _adjustBrandingUri: function () {
        if (this.name.textbox("isValid")) {
            this.listener.webThemeUriFor(this.getName())
                    .done($.proxy(function(value) { this.setUri(value); }, this))
                    .fail($.proxy(function() { this.setUri(""); }, this));
        } else {
            this.setUri("");
        }
    }
});

/** @class */
jscape.account.EditUrlBrandingDialog = jscape.account.UrlBrandingDialog.extend(
    /** @lends {jscape.account.EditUrlBrandingDialog.prototype} */
{
    /** @constructor */
    initialize: function() {
        this._super($("#d-urlbranding-edit"));

        this.title = this.dialog.dialog("header").text() || "";
    },

    /** @override */
    setName: function(value) {
        this._super(value);
        this.dialog.dialog("setTitle", this.title.supplant({0: (value + "").escapeXml()}));
    },

    /** @override */
    setLogoData: function(data) {
        if (data && data.trim().length) {
            this.logoFile.validatebox("options").required = false;
        }
        this._super(data);
    }
});

/** @class */
jscape.account.DeleteUrlBrandingController = Class.extend(
    /** @lends {jscape.account.DeleteUrlBrandingController.prototype} */
{
    deferred: null,

    start: function(themes) {
        this.deferred = $.Deferred();
        this._confirmDelete(themes)
                .done($.proxy(this._deleteConfirmed, this, themes))
                .fail($.proxy(function() { this.deferred.reject(); this.deferred = null; }, this));
        return this.deferred.promise();
    },

    _confirmDelete: function(themes) {
        var text = $.map(themes, function(theme) { return theme.name; }).join(", ");
        return jscape.ConfirmDialog.confirm(
                window.R.string.WEB_THEME_CONFIRM_DELETE_TITLE,
                window.R.string.WEB_THEME_CONFIRM_DELETE_MESSAGE.supplant({0: text.escapeXml()}),
                false);
    },

    _deleteConfirmed: function (themes) {
        $.when.apply(jQuery, $.map(themes, $.proxy(function(theme) { return jscape.API.deleteWebTheme(theme.name); }, this)))
                .done($.proxy(function () { this.deferred.resolve(themes); this.deferred = null; }, this))
                .fail($.proxy(function() { this.deferred.reject(); this.deferred = null; }, this));
    }
});