YUI.add('moodle-form-shortforms', function (Y, NAME) {

/**
 * Provides the form shortforms class.
 *
 * @module moodle-form-shortforms
 */

/**
 * A class for a shortforms.
 *
 * @class M.form.shortforms
 * @constructor
 * @extends Base
 */
function SHORTFORMS() {
    SHORTFORMS.superclass.constructor.apply(this, arguments);
}

var SELECTORS = {
        COLLAPSEEXPAND: '.collapsible-actions .collapseexpand',
        COLLAPSED: '.collapsed',
        FIELDSETCOLLAPSIBLE: 'fieldset.collapsible',
        FIELDSETLEGENDLINK: 'fieldset.collapsible .fheader',
        FHEADER: '.fheader',
        LEGENDFTOGGLER: 'legend.ftoggler'
    },
    CSS = {
        COLLAPSEALL: 'collapse-all',
        COLLAPSED: 'collapsed',
        FHEADER: 'fheader'
    },
    ATTRS = {};

/**
 * The form ID attribute definition.
 *
 * @attribute formid
 * @type String
 * @default ''
 * @writeOnce
 */
ATTRS.formid = {
    value: null
};

Y.extend(SHORTFORMS, Y.Base, {
    /**
     * A reference to the form.
     *
     * @property form
     * @protected
     * @type Node
     * @default null
     */
    form: null,

    /**
     * The initializer for the shortforms instance.
     *
     * @method initializer
     * @protected
     */
    initializer: function() {
        var form = Y.one('#' + this.get('formid')),
            fieldlist,
            btn,
            link,
            idlist;
        if (!form) {
            Y.log('Could not locate the form', 'warn', 'moodle-form-shortforms');
            return;
        }
        // Stores the form in the object.
        this.form = form;
        // Look through collapsible fieldset divs.
        fieldlist = form.all(SELECTORS.FIELDSETCOLLAPSIBLE);
        fieldlist.each(this.process_fieldset, this);

        // Subscribe collapsible fieldsets and buttons to click events.
        form.delegate('click', this.switch_state, SELECTORS.FIELDSETLEGENDLINK, this);
        form.delegate('key', this.switch_state, 'down:enter,32', SELECTORS.FIELDSETLEGENDLINK, this);

        // Handle event, when there's an error in collapsed section.
        Y.Global.on(M.core.globalEvents.FORM_ERROR, this.expand_fieldset, this);

        // Make the collapse/expand a link.
        btn = form.one(SELECTORS.COLLAPSEEXPAND);
        if (btn) {
            link = Y.Node.create('<a href="#"></a>');
            link.setHTML(btn.getHTML());
            link.setAttribute('class', btn.getAttribute('class'));
            link.setAttribute('role', 'button');

            // Get list of IDs controlled by this button to set the aria-controls attribute.
            idlist = [];
            form.all(SELECTORS.FIELDSETLEGENDLINK).each(function(node) {
                idlist[idlist.length] = node.generateID();
            });
            link.setAttribute('aria-controls', idlist.join(' '));

            // Placing the button and binding the event.
            link.on('click', this.set_state_all, this, true);
            link.on('key', this.set_state_all, 'down:enter,32', this, true);
            btn.replace(link);
            this.update_btns(form);
        }
    },

    /**
     * Process the supplied fieldset to add appropriate links, and ARIA
     * roles.
     *
     * @method process_fieldset
     * @param {Node} fieldset The Node relating to the fieldset to add collapsing to.
     * @chainable
     */
    process_fieldset: function(fieldset) {
        // Get legend element.
        var legendelement = fieldset.one(SELECTORS.LEGENDFTOGGLER);

        // Turn headers to links for accessibility.
        var headerlink = Y.Node.create('<a href="#"></a>');
        headerlink.addClass(CSS.FHEADER);
        headerlink.appendChild(legendelement.get('firstChild'));
        headerlink.setAttribute('role', 'button');
        headerlink.setAttribute('aria-controls', fieldset.generateID());
        if (legendelement.ancestor(SELECTORS.COLLAPSED)) {
            headerlink.setAttribute('aria-expanded', 'false');
        } else {
            headerlink.setAttribute('aria-expanded', 'true');
        }
        legendelement.prepend(headerlink);

        return this;
    },

    /**
     * Set the collapsed state for the specified fieldset.
     *
     * @method set_state
     * @param {Node} fieldset The Node relating to the fieldset to set state on.
     * @param {Boolean} [collapsed] Whether the fieldset is collapsed.
     * @chainable
     */
    set_state: function(fieldset, collapsed) {
        var headerlink = fieldset.one(SELECTORS.FHEADER);
        if (collapsed) {
            fieldset.addClass(CSS.COLLAPSED);
            if (headerlink) {
                headerlink.setAttribute('aria-expanded', 'false');
            }
        } else {
            fieldset.removeClass(CSS.COLLAPSED);
            if (headerlink) {
                headerlink.setAttribute('aria-expanded', 'true');
            }
        }
        var statuselement = this.form.one('input[name=mform_isexpanded_' + fieldset.get('id') + ']');
        if (!statuselement) {
            Y.log("M.form.shortforms::switch_state was called on an fieldset without a status field: '" +
                fieldset.get('id') + "'", 'debug', 'moodle-form-shortforms');
            return this;
        }
        statuselement.set('value', collapsed ? 0 : 1);

        return this;
    },

    /**
     * Set the state for all fieldsets in the form.
     *
     * @method set_state_all
     * @param {EventFacade} e
     */
    set_state_all: function(e) {
        e.preventDefault();
        var collapsed = e.target.hasClass(CSS.COLLAPSEALL),
            fieldlist = this.form.all(SELECTORS.FIELDSETCOLLAPSIBLE);
        fieldlist.each(function(node) {
            this.set_state(node, collapsed);
        }, this);
        this.update_btns();
    },

    /**
     * Toggle the state for the fieldset that was clicked.
     *
     * @method switch_state
     * @param {EventFacade} e
     */
    switch_state: function(e) {
        e.preventDefault();
        var fieldset = e.target.ancestor(SELECTORS.FIELDSETCOLLAPSIBLE);
        this.set_state(fieldset, !fieldset.hasClass(CSS.COLLAPSED));
        this.update_btns();
    },

    /**
     * Update the Expand/Collapse all buttons as required.
     *
     * @method update_btns
     * @chainable
     */
    update_btns: function() {
        var btn,
            collapsed = 0,
            expandbtn = false,
            fieldlist;

        btn = this.form.one(SELECTORS.COLLAPSEEXPAND);
        if (!btn) {
            return this;
        }

        // Counting the number of collapsed sections.
        fieldlist = this.form.all(SELECTORS.FIELDSETCOLLAPSIBLE);
        fieldlist.each(function(node) {
            if (node.hasClass(CSS.COLLAPSED)) {
                collapsed++;
            }
        });

        if (collapsed !== 0) {
            expandbtn = true;
        }

        // Updating the button.
        if (expandbtn) {
            btn.removeClass(CSS.COLLAPSEALL);
            btn.setHTML(M.util.get_string('expandall', 'moodle'));
        } else {
            btn.addClass(CSS.COLLAPSEALL);
            btn.setHTML(M.util.get_string('collapseall', 'moodle'));
        }

        return this;
    },
    /**
     * Expand the fieldset, which contains an error.
     *
     * @method expand_fieldset
     * @param {EventFacade} e
     */
    expand_fieldset: function(e) {
        e.stopPropagation();
        var formid = e.formid;
        if (formid === this.form.getAttribute('id')) {
            var errorfieldset = Y.one('#' + e.elementid).ancestor('fieldset');
            if (errorfieldset) {
                this.set_state(errorfieldset, false);
            }

        }
   }
}, {
    NAME: 'moodle-form-shortforms',
    ATTRS: ATTRS
});

M.form = M.form || {};
M.form.shortforms = M.form.shortforms || function(params) {
    return new SHORTFORMS(params);
};


}, '@VERSION@', {"requires": ["node", "base", "selector-css3", "moodle-core-event"]});
