Source: Map/AbsCode.js

"use strict";

/*global require*/

var defineProperties = require('terriajs-cesium/Source/Core/defineProperties');
var knockout = require('terriajs-cesium/Source/ThirdParty/knockout');
var defined = require('terriajs-cesium/Source/Core/defined');

var inherit = require('../Core/inherit');
var Concept = require('../Map/Concept');

/**
 * Represents an ABS code associated with a AbsConcept.
 * An AbsCode may contains an array one of more child AbsCodes.
 *
 * @alias AbsCode
 * @constructor
 * @extends {Concept}
 */
var AbsCode = function(code, name, concept) {
    Concept.call(this, name);
    /**
     * Gets or sets the value of the abs code.
     * @type {String}
     */
    this.code = code;

    /**
     * Gets the list of abs codes contained in this group.  This property is observable.
     * @type {AbsCode[]}
     */
    this.items = [];

    /**
     * Gets or sets the parent for a code.  This property is observable.
     * @type {AbsCode|AbsConcept}
     */
    this.parent = undefined;

    /**
     * Gets or sets the ultimate parent concept for a code.  This property is observable.
     * @type {AbsConcept}
     */
    this.concept = concept;

    /**
     * Flag to say if this if this concept only allows more than one active child.
     * Defaults to the same as concept.
     * Only meaningful if this concept has an items array.
     * @type {Boolean}
     */
    this.allowMultiple = this.concept.allowMultiple;

    /**
     * Gets or sets a value indicating whether this abs code is currently open.  When an
     * item is open, its child items (if any) are visible.  This property is observable.
     * @type {Boolean}
     */
    this.isOpen = false;

    /**
     * Gets or sets a value indicating whether this abs code is currently active.  When a
     * code is active, it is included in the abs data query.  This property is observable.
     * @type {Boolean}
     */
    this.isActive = false;

    /**
     * Flag to say if this is selectable.  This property is observable.
     * @type {Boolean}
     */
    this.isSelectable = true;  //for ko

    knockout.track(this, ['code', 'items', 'isOpen', 'isActive']);
};

inherit(Concept, AbsCode);

defineProperties(AbsCode.prototype, {
    /**
     * Gets a value indicating whether this item has child items.
     * @type {Boolean}
     */
    hasChildren : {
        get : function() {
            return this.items.length > 0;
        }
    }

});

/**
 * Toggles the {@link AbsCode#isOpen} property.  If this item's list of children is open,
 * calling this method will close it.  If the list is closed, calling this method will open it.
 */
AbsCode.prototype.toggleOpen = function() {
    this.isOpen = !this.isOpen;
};

/**
 * Toggles the {@link AbsCode#isActive} property.
 */
AbsCode.prototype.toggleActive = function(test) {
    this.isActive = !this.isActive;
    function clearParents(code) {
        if (defined(code.parent)) {
            code.parent.isActive = false;
            clearParents(code.parent);
        }
    }
    function clearChildren(code) {
        code.items.forEach( function(item) {
            item.isActive = false;
            clearChildren(item);
        });
    }
    function clearSiblings(code) {
        if (!code.parent.allowMultiple) {
            code.parent.items.forEach( function(item) {
                if (item !== code) {
                    item.isActive = false;
                }
            });
        }
    }
    if (this.isActive) {
        clearParents(this);
        clearChildren(this);
        clearSiblings(this);
    }
};

module.exports = AbsCode;