/// class PD.Commands.Command

PD.Commands.Command =
Class.extend({

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

    _state: null,
    _props: null,
    
    //===================================
    // CONSTRUCTOR
    //===================================

    init: function (inits) {
        this._uid = uuid.v4();
        this._inits = inits || {};
        this._state = {};
        this._props = this._initProps();
        this.setDefaults();
    },

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

    get_id: function () {
        return this.props("id");
    },

    get_uid: function () {
        return this._uid;
    },

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

    inits: function (id, value) {

        var result = null;

        if (id === undefined) {
            result = this._inits;
        }
        else {
            if (value === undefined) {
                result = this._inits[id];
            }
            else {
                this._inits[id] = value;
            }
        }

        return result;


    },

    state: function (id, value) {

        var result = null;

        if (id === undefined) {
            result = this._state;
        }
        else {
            if (arguments.length < 2) {
                result = this._state[id];
            }
            else {
                this._state[id] = value;
            }
        }

        return result;

    },

    props: function (id, value) {

        var result = null;

        if (id === undefined) {
            result = this._props;
        }
        else {
            if (value !== undefined) {
                this._props.set(id, value);
            }
            result = this._props.get(id);
        }

        return result;

    },

    execute: function (e) {
        this._mergeCallback("_success", e);
        this._mergeCallback("_error", e);
        this._mergeCallback("_complete", e);
    },

    bind: function (fn) {
        var args = this._getCommandEventArgs();
        if (_.isFunction(fn)) {
            args.intializing = true;
            fn(args);
        }
    },

    update: function (fn, scope) {

        var that = this;

        this.props().on("change", function (e) {
            if (_.isFunction(fn)) {
                var args = that._getCommandEventArgs();
                args.intializing = false;
                fn(args);
            }
        }, scope);

    },

    //===================================
    // PROTECTED METHODS
    //===================================

    setState: function (state, overwrite) {
        for (key in this.state()) {
            if (key in state) {
                this.state(key, state[key]);
            }
            else if (overwrite) {
                this.state(key, null);
            }
        }
    },

    setDefaults: function () {
        //do nothing;
    },

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

    _getCommandEventArgs: function () {
        return {
            command: this,
            enabled: this.props("enabled"),
            icon: this.props("icon"),
            label: this.props("label"),
            tooltip: this.props("tooltip"),
            visible: this.props("visible")
        };
    },

    _mergeCallback: function (callbackName, args) {

        var that = this,
            args = args || {};

        if (args[callbackName]) {
            this[callbackName] = function (e) {
                that[callbackName](e);
                args[callbackName](e);
            }
        }

    },

    _initProps: function () {

        var result = Backbone.Model.extend({
            defaults: {
                id: null,
                enabled: null,
                icon: null,
                label: null,
                tooltip: null,
                visible: true
            }
        });

        return new result();

    },

    success: function () {

    },

    error: function () {

    },

    complete: function () {

    }

});