/// class PD.Context.Context

PD.Context.Context =
Class.extend({

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

    _id: null,
    _name: null,
    _options: null,
    _parent: null,
    _events: null,
    _commands: null,
    _tags: null,

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

    init: function (options) {

        this._options = _.extend({
            id: uuid.v4(),
            name: "",
            parent: null,
            tags: []
        }, options);

        this._options.id = this._options.id.toLowerCase();

        this._id = this.get_options().id;
        this._name = this.get_options().name;
        this._parent = this.get_options().parent;
        this._commands = new PD.Commands.CommandContext({
            contextId: this.get_id()
        });
        this._events = new PD.Events.EventContext();
        this._tags = this.get_options().tags;

    },

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

    get_id: function () {
        return this._id;
    },

    get_name: function () {
        return this._name;
    },

    get_options: function () {
        return this._options;
    },

    get_parent: function () {
        return this._parent;
    },

    get_commands: function () {
        return this._commands;
    },

    get_events: function () {
        return this._events;
    },

    get_tags: function () {
        return this._tags;
    },

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

    findClosestContext: function (tags, matchAny) {

        var result = null,
            target = this;

        matchAny = matchAny == null ? false : true;

        while (target != null) {

            if (target.isTaggedWith(tags, matchAny)) {
                result = target;
                break;
            }

            target = target.get_parent();

        }

        return result;

    },

    isTaggedWith: function (tags, matchAny) {

        var result = false,
            unmatched = _.difference(tags, this.get_tags());

        result = (matchAny === false && unmatched.length === 0)
            || (matchAny === true && unmatched.length < tags.length);

        return result;

    }

});