jscape.settings = jscape.settings || {};

/** @class */
jscape.SearchingServiceConfiguration = Class.extend(
    /** @lends {jscape.SearchingServiceConfiguration.prototype} */
{
    /** @constructor */
    initialize: function(a, b, c, d, e) {
        this.indexingPeriod = parseInt(a) || null;
        this.updateFileIndexUponUpload = b || false;
        this.updateFileIndexUponRename = c || false;
        this.updateAccountIndexUponUpdating = d || false;
        this.updateGroupIndexUponUpdating = e || false;
    }
});
jscape.SearchingServiceConfiguration.fromJSON = function(data) {
    return data ? new jscape.SearchingServiceConfiguration(data.indexingPeriod, data.updateFileIndexUponUpload, data.updateFileIndexUponRename, data.updateAccountIndexUponUpdating, data.updateGroupIndexUponUpdating) : null;
};

/** @class */
jscape.settings.SearchingModule = jscape.settings.SettingsModule.extend(
    /** @lends {jscape.settings.SearchingModule.prototype} */
{
    onCreate: function(managementService) {
        this._super.apply(this, arguments);

        this.controller = new jscape.settings.SearchingController();
        this.controller.onCreate(managementService, new jscape.SearchingService(this.managementService));
    },

    onStart: function () {
        this.controller.onStart();
    },

    onPause: function () {
        if (this.controller.hasChanged()) {
            this._confirmAndApply([this.controller]);
        }
    },

    onResume: function() {
        this.controller.onResume();
    }
});

/** @class */
jscape.SearchingService = Class.extend(
    /** @lends {jscape.SearchingService.prototype} */
{
    STATUS: {IN_PROGRESS: "IN_PROGRESS", SUCCESS: "SUCCESS"},
    POLL_DELAY: 5000,

    timerId: null,

    /** @constructor */
    initialize: function(managementService) {
        this.managementService = managementService;
    },

    rebuildIndex: function () {
        var deferred = $.Deferred();
        this.managementService.startSearchFileIndexing()
                .done($.proxy(this._poll, this, deferred, 1000))
                .fail(function () { deferred.reject(); });
        return deferred.promise();
    },

    _poll: function (deferred, delay) {
        if (this.timerId) {
            clearTimeout(this.timerId);
        }
        this.timerId = setTimeout($.proxy(function () {
            this.managementService.getSearchFileIndexingStats()
                    .done($.proxy(function (stats) {
                              var state = stats && stats.state ? stats.state : undefined;
                              if (this.STATUS.IN_PROGRESS === state) {
                                  this._poll(deferred, this.POLL_DELAY);
                              } else {
                                  if (this.STATUS.SUCCESS === state) {
                                      deferred.resolve();
                                  } else {
                                      deferred.reject();
                                  }
                              }
                          }, this))
                    .fail(function () { deferred.reject(); });
        }, this), delay || 0);
    }
});

/** @class */
jscape.settings.SearchingController = Class.extend(
    /** @lends {jscape.settings.SearchingController.prototype} */
{
    DEFAULT_CONFIG: new jscape.SearchingServiceConfiguration(),

    config: null,
    view: null,

    onCreate: function(managementService, searchingService) {
        this.managementService = managementService;
        this.searchingService = searchingService;
    },

    onStart: function () {
        if (this.view == null) {
            this.view = new jscape.settings.SearchingView();
        }
        this.view.show(this);
    },

    onResume: function () {
        this.managementService.getSearchingServiceConfiguration()
                .done($.proxy(function (config) { this.config = config; }, this))
                .fail($.proxy(function () { this.config = this.DEFAULT_CONFIG; }, this))
                .always($.proxy(function () { this.view && this._setupView(this.config); }, this));
    },

    hasChanged: function () {
        return this.config != null && !Object._equals(this.config, this._createConfiguration());
    },

    onApply: function () {
        return this.managementService.setSearchingServiceConfiguration(this._createConfiguration())
                .done($.proxy(function (config) { this.config = config; }, this))
                .done($.proxy(this._fireApplySuccess, this));
    },

    onDiscard: function () {
        this._setupView(this.config);
        return $.Deferred().resolve().promise();
    },

    onRebuildIndex: function() {
        return this.searchingService.rebuildIndex()
                .done($.proxy(this._fireRebuildIndexSuccess, this))
                .fail($.proxy(this._fireRebuildIndexError, this));
    },

    _createConfiguration: function() {
        return new jscape.SearchingServiceConfiguration(this.view.getIndexingPeriod(),
                                                        this.view.getUpdateFileIndexUponUpload(),
                                                        this.view.getUpdateFileIndexUponRename(),
                                                        this.view.getUpdateAccountIndexUponUpdate(),
                                                        this.view.getUpdateGroupIndexUponUpdate());
    },

    _setupView: function(config) {
        if (config) {
            this.view.setIndexingPeriod(config.indexingPeriod);
            this.view.setUpdateFileIndexUponUpload(config.updateFileIndexUponUpload);
            this.view.setUpdateFileIndexUponRename(config.updateFileIndexUponRename);
            this.view.setUpdateAccountIndexUponUpdate(config.updateAccountIndexUponUpdating);
            this.view.setUpdateGroupIndexUponUpdate(config.updateGroupIndexUponUpdating);
        }
    },

    _fireApplySuccess: function () {
        this._broadcastMessage(window.R.string.APPLICATION_SUCCESS_APPLY);
    },

    _fireRebuildIndexSuccess: function(success) {
        this._broadcastMessage(window.R.string.SETTINGS_SUCCESS_FILE_INDEX);
    },

    _fireRebuildIndexError: function(success) {
        this._broadcastMessage(window.R.string.SETTINGS_ERROR_FILE_INDEX);
    },

    _broadcastMessage: function(message) {
        $(document).triggerHandler("broadcast", [message]);
    }
});

/** @class */
jscape.settings.SearchingView = Class.extend(
    /** @lends {jscape.settings.SearchingView.prototype} */
{
    INDEXING_PERIOD_FACTOR: 1000 * 60 * 60,
    DEFAULT_INDEXING_PERIOD: 24,

    /** @constructor */
    initialize: function() {
        this.fieldset = $("fieldset[name=searchingservicefields]");

        this.rebuildIndexEnabled = $("input[name=reindex]:checkbox", this.fieldset);
        this.rebuildIndexEnabled.change($.proxy(function() {
            var enabled = this.rebuildIndexEnabled.is(":checked");
            this.rebuildIndexPeriod.numberspinner(enabled ? "enable" : "disable");
        }, this));
        this.rebuildIndexPeriod = $("input[name=indexperiod]", this.fieldset).numberspinner({disabled: true, min: 1, max: 1000, width: 60});

        this.updateFileIndexUponUpload = $("input[name=fileupload]:checkbox", this.fieldset);
        this.updateFileIndexUponRename = $("input[name=filerename]:checkbox", this.fieldset);
        this.updateAccountIndexUponUpdate = $("input[name=accountupdate]:checkbox", this.fieldset);
        this.updateGroupIndexUponUpdate = $("input[name=groupupdate]:checkbox", this.fieldset);

        this.rebuildButton = $("a[role=button][name=rebuild]", this.fieldset).linkbutton({onClick: $.proxy(this._onClick$RebuildButton, this)});
        this.applyButton = $("a[role=button][name=apply]", this.fieldset).linkbutton({onClick: $.proxy(this._onClick$ApplyButton, this)});
        this.discardButton = $("a[role=button][name=discard]", this.fieldset).linkbutton({onClick: $.proxy(this._onClick$DiscardButton, this)});
    },

    show: function(listener) {
        this.listener = listener || jscape.settings.SearchingView.LISTENER;
    },

    getIndexingPeriod: function() {
        return this.rebuildIndexEnabled.is(":checked") ? parseInt(this.rebuildIndexPeriod.numberspinner("getValue")) * this.INDEXING_PERIOD_FACTOR : null;
    },

    setIndexingPeriod: function(value) {
        this.rebuildIndexEnabled.prop("checked", value != null).change();
        this.rebuildIndexPeriod.numberspinner("setValue", value != null ? parseInt(value) / this.INDEXING_PERIOD_FACTOR : this.DEFAULT_INDEXING_PERIOD);
    },

    getUpdateFileIndexUponUpload: function() {
        return this.updateFileIndexUponUpload.is(":checked");
    },

    setUpdateFileIndexUponUpload: function(value) {
        this.updateFileIndexUponUpload.prop("checked", !!value);
    },

    getUpdateFileIndexUponRename: function() {
        return this.updateFileIndexUponRename.is(":checked");
    },

    setUpdateFileIndexUponRename: function(value) {
        this.updateFileIndexUponRename.prop("checked", !!value);
    },

    getUpdateAccountIndexUponUpdate: function() {
        return this.updateAccountIndexUponUpdate.is(":checked");
    },

    setUpdateAccountIndexUponUpdate: function(value) {
        this.updateAccountIndexUponUpdate.prop("checked", !!value);
    },

    getUpdateGroupIndexUponUpdate: function() {
        return this.updateGroupIndexUponUpdate.is(":checked");
    },

    setUpdateGroupIndexUponUpdate: function(value) {
        this.updateGroupIndexUponUpdate.prop("checked", !!value);
    },

    _onClick$RebuildButton: function() {
        this.rebuildButton.linkbutton("disable");
        this._toggleButtonText(this.rebuildButton);

        this.listener.onRebuildIndex(this)
                .always($.proxy(function() {
                    this.rebuildButton.linkbutton("enable");
                    this._toggleButtonText(this.rebuildButton);
                }, this));
    },

    _onClick$ApplyButton: function () {
        if (this.fieldset.form("validate")) {
            this.applyButton.linkbutton("disable");
            this.listener.onApply()
                    .always($.proxy(function() { this.applyButton.linkbutton("enable"); }, this));
        }
    },

    _onClick$DiscardButton: function () {
        this.listener.onDiscard();
    },

    _toggleButtonText: function(button) {
        var text = button.text();
        button.html(button.html().replace(text, button.data("toggle-text") || text));
        button.data("toggle-text", text);
    }
});
jscape.settings.SearchingView.LISTENER = {
    onRebuildIndex: $.noop,
    onApply: $.noop,
    onDiscard: $.noop
};
