/// 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) {
    
        var that = this,
            message = "",
            source = null;

        if (e.dirtySources.count() === 1) {
            message = "There are unsaved changes on this page.\n\nHow would you like to proceed?"
        }
        else {
            message = "There are unsaved changes on multiple pages.\n\nHow would you like to proceed?"
        }

        PD.Web.UI.RadioDialog.warn({
            title: "Unsaved Changes Detected",
            message: message,
            ok: function (args) {

                args.close();

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

            },
            radios: [
                { value: "save", label: "<b>Attempt to automatically save the changes and proceed.</b><br/>The application will attempt to automatically save the changes you have made, if the changes cannot be saved you will be prompted to attempt the save operation manually." },
                { value: "discard", label: "<b>Discard the changes and proceed.</b><br/>Any changes you have made will be discarded and the application will continue to execute your request." }
            ]
        });

    },

    _showFailedCommitMessage: function (e) {

        var messages = [];

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

        PD.Web.UI.ErrorDialog.show({
            message: "Failed to save changes for the following forms:",
            errors: messages
        })

    }

});