/// class PD.Web.UI.MutationManager

PD.Web.UI.MutationManager =
Class.extend({

    //================================
    // FIELDS
    //================================

    _activeSourceId: null,	
    _sources: null,

    //================================
    // CONSTRUCTOR
    //================================

    init: function () {
	
        var that = this;
	
        this._sources = new PD.Web.UI.MutationSourceCollection();

        $(document).on("click", "A", function (e) {
            var target = e.currentTarget;
            if (target.href.length > 0 && (target.hash == null || target.hash.length === 0)) {
                e.preventDefault();
                e.stopPropagation();
                that.execute(function () {
                    window.location = target.href;
                }, true);
            }
        });
	
    },

    //================================
    // PROPERTIES
    //================================

    get_sources: function () {
        return this._sources;
    },

    //================================
    // PUBLIC METHODS
    //================================

    execute: function (actionFn, checkAllSources) {

        var source = null,
            dirtySources = new PD.BCL.List();

        if (checkAllSources) {
            dirtySources = this.get_sources().getDirty();
        }
        else {
            source = this.get_sources().get(this._activeSourceId);
            if (source && source.get_isDirty()) {
                dirtySources.add(source);
            }
        }

        this._react({
            action: actionFn,
            dirtySources: dirtySources,
            failedSources: new PD.BCL.List()
        });

    },

    isActiveSource: function (id) {
        return this._activeSource === id;
    },

    setActiveSource: function (id) {
        if (this.get_sources().exists(id)) {
            this._activeSourceId = id;
        }
        else {
            throw "Supplied source does not exist. Failed to monitor changes!";
        }
    },

    getActiveSource: function () {
        return this.get_sources().get(this._activeSourceId);
    },

    addSource: function (options) {
        this.get_sources().add(new PD.Web.UI.MutationSource(options));
    },

    removeSource: function (id) {
        this.get_sources().remove(id);
    },

    clearSources: function () {
        this.get_sources().clear();
    },

    isDirty: function (id) {

        var result = false,
            source = null;

        if (id !== undefined) {
            source = this.get_sources().get(id)
            if (source) {
                result = source.get_isDirty();
            }
        }
        else {
            result = this.get_sources().getDirty().length > 0;
        }

        return result;

    },

    //================================
    // PRIVATE METHODS
    //================================

    _react: function (e) {

        if (e.dirtySources.count() === 0) {
            e.action();
            return;
        }

        this._showHandleMessage(e);

    },

    _attemptHandle: function (e) {

        if (e.dirtySources.count() > 0) {
            this._attemptResolve(e);
        }
        else {
            this._attemptAction(e);
        }

    },

    _attemptResolve: function (e) {
        
        var that = this,
            source = e.dirtySources.first();

        e.dirtySources.remove(source);

        source.resolve(function () {
            source.setClean();
            that._attemptHandle(e);
        }, function () {
            e.failedSources.add(source);
            that._attemptHandle(e);
        });

    },

    _attemptAction: function (e) {
    
        if (e.failedSources.count() > 0) {
            this._showFailedCommitMessage(e);
        }
        else {
            e.action();
        }

    },

    _showHandleMessage: function (e) {

        PDJS.Shared.Dialogs.UnsavedChangesDialog.show((args) => {

            args.close();

            let first =
                _.first(args.selected);

            if (first == null) {
                return;
            }

            switch (first.value) {
                case "save":
                    this._attemptHandle(e);
                    break;
                case "discard":
                    e.dirtySources.clear()
                    e.failedSources.clear()
                    this.get_sources().setClean();
                    this._react(e);
                    break;
            }

        });

    },

    _showFailedCommitMessage: function (e) {

        var messages = [];

        e.failedSources.each(function (index, source) {
            messages[messages.length] = { message: source.get_name() };
        });

        Jade.UI.Dialogs.ErrorDialogLauncher.open({
            header: "Failed to save changes for the following forms:",
            messages: messages
        });

    }

});