Core.createNamespace('nl.code.elementfolder');

/**
 * ElementFolder Class
 */
nl.code.elementfolder.ElementFolder = new Class({
    /**
     * @var FoldableElement
     */
    active: null,

    /**
     * @var array
     */
    foldable_element_arr: [],

    /**
     * @var boolean
     */
    allow_multiple_colapsed: false,

    /**
     * Constructor
     *
     * @param string, CSS selector for the root element
     * @param string, CSS selector for the children
     * @param string, CSS selector for the anchor to add the collapse/expand events on
     * @param string, the classname for the active state
     * @param boolean, allow multiple colapsed children
     * @param Function (optional), the constructor for the foldable element object
     */
    initialize: function(root_selector, child_selector, anchor_selector, active_state_classname, allow_multiple_colapsed, foldable_element_class) {
        var root = $(document.body).getElement(root_selector);

        // guard: stop if the root element is not found
        if (! root) {
            return;
        }

        if (! $type(foldable_element_class)) {
            foldable_element_class = nl.code.elementfolder.FoldableElement;
        }

        // get the child elements
        var child_arr = root.getElements(child_selector);
        for (var i = 0; i < child_arr.length; i++) {
            var element = new foldable_element_class(this, child_arr[i], anchor_selector, active_state_classname);

            if (element.isActive()) {
                this.active = element;
            }

            this.foldable_element_arr.push(element);
        }
    },

    /**
     * Handle the click on a foldable element
     *
     * @param FoldableElement
     * @return void
     */
    handleClick: function(foldable_element) {
        if (this.allow_multiple_colapsed) {
            if (foldable_element.isActive()) {
                foldable_element.setInActive();
            } else {
                foldable_element.setActive();
            }
        } else {
            if (this.active == foldable_element) {
                this.active.setInActive();
                this.active = null;
            } else {
                if (this.active) {
                    this.active.setInActive();
                }

                this.active = foldable_element;
                this.active.setActive();
            }
        }
    }
});

/**
 * FoldableElement
 */
nl.code.elementfolder.FoldableElement = new Class({
    /**
     * @var Element
     */
    container: null,

    /**
     * @var string
     */
    active_state_classname: '',

    /**
     * Constructor
     *
     * @param ElementFolder
     * @param Element, the container
     * @param string, CSS selector for the anchor to add the collapse/expand events on
     * @param string, the classname for the active state
     */
    initialize: function(element_folder, container, anchor_selector, active_state_classname) {
        this.container = container;
        this.active_state_classname = active_state_classname;

        var anchor = this.container.getElement(anchor_selector);

        // guard: stop no actor found
        if (! anchor) {
            return;
        }

        var thisObject = this;
        anchor.removeEvents();
        anchor.addEvents({
            'click': function(event) {
                event.stop();

                element_folder.handleClick(thisObject);
            },
            'focus': function(e) {
                this.blur();
            }
        });
    },

    /**
     * @return boolean
     */
    isActive: function() {
        return this.container.hasClass(this.active_state_classname);
    },

    /**
     * @return void
     */
    setActive: function() {
        this.container.addClass(this.active_state_classname);
    },

    /**
     * @return void
     */
    setInActive: function() {
        this.container.removeClass(this.active_state_classname);
    }
});