(function() {

    // TODO: this should be in a shared dependency
    // Ensure Array.indexOf exists
    // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/indexOf

    if (!Array.prototype.indexOf) {

        Array.prototype.indexOf = function(elt /*, from*/) {

            var len = this.length >>> 0,
                from = Number(arguments[1]) || 0;

            from = (from < 0) ? Math.ceil(from) : Math.floor(from);

            if (from < 0) from += len;

            for (; from < len; from++) {

                if (from in this && this[from] === elt) return from;
            }

            return -1;
        };
    }

    // --- Shortcuts ---


    var Event = YAHOO.util.Event,
        DOM = YAHOO.util.Dom,
        $Y = YAHOO.util.Selector.query;


    // --- Initialise namespaces ---


    BV = BV || {};  // NB: "BV" namespace is pre-declared in the HTML

    BV.page = BV.page || {};
    BV.ui = BV.ui || {};
    BV.util = BV.util || {};
    BV.i18n = BV.i18n || {};


    // --- Initialise i18n strings ---


    BV.i18n.ui = BV.i18n.ui || {};
    BV.i18n.widget = BV.i18n.widget || {};
    BV.i18n.page = BV.i18n.page || {};

    BV.i18n.ui.contentPaginator = {
        nextPage: "Neste",
        previousPage: "Forrige"
    }

    BV.i18n.widget.DataTable = {
        empty: "Ingen poster funnet"
    }


    // --- Initialise YUI ---


    Event.throwErrors = true;


    // --- Generic functions ---


    // TODO: this should be in a shared dependency
    BV.util.String = {

        /**
         *
         */
        htmlspecialchars: function(str) {

            if (str === undefined) return "";

            return str.replace(/[(<>"&]/g, function(match){
                return (match == "<") ? "&lt;" :
                    (match == ">") ? "&gt;" :
                    (match == '"') ? "&quot;" :
                    (match == "&") ? "&amp;" : "";
            });
        }
    }

    // TODO: this should be in a shared dependency
    BV.ui.Interaction = {

        /**
         *
         */
        collapsible: function(el, options) {

            var handleClick = function(ev, collapseTarget) {

                var shown = DOM.getStyle(collapseTarget, "display") == "block",
                    attributes = { height: {} },
                    anim = new YAHOO.util.Anim(collapseTarget, attributes, 0.2),
                    sectionRegion;

                if (shown) {

                    attributes.height.to = 0;
                    sectionRegion = DOM.getRegion(collapseTarget);
                    this.bv_height = sectionRegion.bottom - sectionRegion.top;
                    this.addClass("collapsed");

                    anim.onComplete.subscribe(function() {
                        DOM.setStyle(collapseTarget, "display", "none");
                    });
                }
                else {

                    attributes.height.to = this.bv_height;
                    DOM.setStyle(collapseTarget, "display", "block");
                    this.removeClass("collapsed");

                    anim.onComplete.subscribe(function() {
                        DOM.setStyle(collapseTarget, "height", "auto");
                    });
                }

                anim.animate();
            };

            DOM.batch(el, function(el) {

                var button = new YAHOO.util.Element(document.createElement("button")),
                    collapseTarget = el.nextSibling,
                    sectionRegion = DOM.getRegion(collapseTarget);

                button.addClass("toggler");
                button.set("innerHTML", el.innerHTML);
                button.bv_height = sectionRegion.bottom - sectionRegion.top;
                button.on("click", handleClick, collapseTarget);

                DOM.addClass(collapseTarget, "collapseTarget");
                DOM.insertBefore(button, el);
                el.parentNode.removeChild(el);

                if (el.innerHTML == "Fylke" || options.collapseNested && DOM.getAncestorByClassName(button, "collapseTarget")) {

                    DOM.setStyle(collapseTarget, "height", 0);
                    DOM.setStyle(collapseTarget, "display", "none");
                    button.addClass("collapsed");
                }
                
                               
            });
        }
    }


    // --- Code specific to project list ---


    // Shortcuts
    var htmlspecialchars = BV.util.String.htmlspecialchars;

    // i18n for this page
    BV.i18n.page.KDUProjectList = {

        createNew: "Lag ny",
        tableHeader: "{rowCount} kartlegginger",
        noName: "Ingen navn"
    }

    /**
     * Page class (singleton)
     * @constructor
     */
    BV.page.KDUProjectList = function(data) {

        // Set up table
        
        var tableConfig;
        this.dataSource = new YAHOO.util.LocalDataSource(data)

        this.dataSource.responseType = YAHOO.util.LocalDataSource.TYPE_JSON;
        this.dataSource.responseSchema = this.schema;
        this.dataSource.subscribe(
            "responseParseEvent",
            this.dataSourceApplyFilters,
            this, true
        );

        this.paginator = new YAHOO.widget.Paginator({
            rowsPerPage: this.rowsPerPage,
            template: "{PreviousPageLink} {PageLinks} {NextPageLink}",
            previousPageLinkLabel: BV.i18n.ui.contentPaginator.previousPage,
            nextPageLinkLabel: BV.i18n.ui.contentPaginator.nextPage
        });

        tableConfig = {
            MSG_EMPTY: BV.i18n.widget.DataTable.empty,
	    sortedBy: { key: "modifiedDate", dir: YAHOO.widget.DataTable.CLASS_DESC },
            paginator: this.paginator
        };

        this.dataTable = new YAHOO.widget.DataTable(
            "projectListTable",
            this.columns,
            this.dataSource,
            tableConfig
        );

        // Set up filters

        DOM.get("projectFilters").appendChild(this.createFilterMarkup(data.filters));
        BV.ui.Interaction.collapsible($Y("#projectFilters li h6"), {
            collapseNested: true
        });

        // Handler for "create new" link; make it pop-up a small dialog (only exists if logged in)

        Event.addListener("newProjectBtn", "click", this._handleNewProjectClick, this, true);
    };

    /**
     * Datatable formatter
     */
    BV.page.KDUProjectList.formatFieldProsjektnavn = function(el, record, column, data) {

        var linkText = (data == "") ?
            "<em>" + htmlspecialchars(BV.i18n.page.KDUProjectList.noName) + "</em>" :
            htmlspecialchars(data);

        el.innerHTML =
            '<a href="' + htmlspecialchars(record.getData("projectUrl")) + '">' +
            linkText + '</a>';
    };

    /**
     * Datatable formatter
     */
    BV.page.KDUProjectList.formatModifiedDate = function(el, record, column, data) {
	if (data != ""){
	    date = new Date(data * 1000)
	    var datestring = YAHOO.util.Date.format(date, {format:'%d.%m.%Y'});
            el.innerHTML = datestring;
	}
    };


    /**
     * Page class methods
     */
    BV.page.KDUProjectList.prototype = {

        /**
         *
         */
        createFilterMarkup: function(filterSpecs, level) {

            var filterListEl = document.createElement("ul"),
                filterGroup,
                groupEl,
                groupTitleEl,
                groupFiltersEl,
                singleFilter,
                singleFilterEl,
                labelEl,
                inputEl;

            level = level ? level : 1;

            for (var i = 0, len = filterSpecs.length; i < len; ++i) {
                
                filterGroup = filterSpecs[i];

                groupEl = document.createElement("li");

                groupTitleEl = document.createElement("h6");
                groupTitleEl.className = "level" + level;
                groupTitleEl.appendChild(document.createTextNode(filterGroup.title));
                groupEl.appendChild(groupTitleEl);

                if (filterGroup.children) {

                    groupEl.appendChild(
                        this.createFilterMarkup(filterGroup.children, level + 1)
                    );
                }

                if (filterGroup.filters) {

                    groupFiltersEl = document.createElement("ul");

                    for (var j = 0, lenF = filterGroup.filters.length; j < lenF; ++j) {

                        singleFilter = filterGroup.filters[j];

                        singleFilterEl = document.createElement("li");
                        labelEl = document.createElement("label");
                        inputEl = document.createElement("input");

                        inputEl.type = "checkbox";

                        labelEl.appendChild(inputEl);
                        labelEl.appendChild(
                            document.createTextNode(singleFilter.title)
                        );

                        singleFilterEl.appendChild(labelEl);
                        groupFiltersEl.appendChild(singleFilterEl);

                        Event.addListener(
                            inputEl,
                            "click",
                            this.handleFilterClick,
                            { filterGroup: filterGroup, filter: singleFilter },
                            this
                        );
                    }

                    groupEl.appendChild(groupFiltersEl);
                }

                filterListEl.appendChild(groupEl);
            }

            return filterListEl;
        },

        /**
         *
         */
        handleFilterClick: function(ev, filterData) {
                       var filterGroup = filterData.filterGroup,
                filter = filterData.filter,
                target = Event.getTarget(ev);

            if (target.checked) {

                if (!this._activeFilters[filterGroup.key]) {

                    this._activeFilters[filterGroup.key] = {
                        filterGroup: filterGroup,
                        filters: []
                    };
                }

                this._activeFilters[filterGroup.key].filters.push(filter);
            }
            else {

                var activeFilterGroup = this._activeFilters[filterGroup.key];

                for (var i = 0, len = activeFilterGroup.filters.length; i < len; ++i) {

                    if (activeFilterGroup.filters[i].value == filter.value) {

                        activeFilterGroup.filters.splice(i, 1);

                        if (!activeFilterGroup.filters.length) {

                            delete this._activeFilters[filterGroup.key];
                        }

                        break;
                    }
                }
            }

            var callback = {
                success: this.dataTable.onDataReturnInitializeTable,
                failure: this.dataTable.onDataReturnInitializeTable,
                scope: this.dataTable,
                argument: this.dataTable.getState()
            };
            
            
            this.dataSource.sendRequest(null, callback);  // refresh table
            
        },

        /**
         *
         */
        dataSourceApplyFilters: function(transaction) {

            var results = transaction.response.results,
                filteredResults = [],
                activeFilterGroup,
                foundInGroup,
                valueToMatch,
                valueToTest;

            resultsLoop: for (var i = 0, lenI = results.length; i < lenI; ++i) {

                // Test each possible result...

                for (var activeFilterGroupName in this._activeFilters) {

                    // ... against all filter groups as an AND condition...
					activeFilterGroup = this._activeFilters[activeFilterGroupName];
                    
                    foundInGroup = false;

                    for (var j = 0, lenJ = activeFilterGroup.filters.length; j < lenJ; ++j) {

                        // ... but within each group as an OR condition

                        valueToMatch = activeFilterGroup.filters[j].value;
                        valueToTest = results[i][activeFilterGroup.filterGroup.key];

                        if (YAHOO.lang.isArray(valueToTest)) {

                            if (valueToTest.indexOf(valueToMatch) !== -1) {

                                foundInGroup = true;
                                break;
                            }
                        }
                        else if (valueToTest == valueToMatch) {

                            foundInGroup = true;
                            break;
                        }
                    }

                    if (!foundInGroup) {

                        continue resultsLoop;  // NOTE: note the label
                    }
                }

                // if we got here, this result matched something in all groups

                filteredResults.push(results[i]);
            }
            transaction.response.results = filteredResults;
        },

        /**
         *
         */
        updateHeader: function() {
	    //This method can be removed,
	    //no longer in use on updates since counter is removed from html.
            DOM.get("projectListHeader").innerHTML =
                YAHOO.lang.substitute(
                    BV.i18n.page.KDUProjectList.tableHeader,
                    { rowCount: this.dataTable.getRecordSet().getLength() });
        },


        /**
         * Event handler for click on "make new project" button
         */
        _handleNewProjectClick: function() {

            if (!this.newProjectDialog) {

                this.newProjectDialog = new YAHOO.widget.Dialog("newProjectDialog", {
                        buttons: [
                            {
                                text: BV.i18n.page.KDUProjectList.createNew,
                                isDefault: true,
                                handler: function() { this.submit(); }
                            }
                        ],
                        close: true,
                        context: ["newProjectBtn", "tl", "tl", ["beforeShow", "windowResize"]],
                        draggable: false,
                        effect: { duration: 0.25, effect: YAHOO.widget.ContainerEffect.FADE },
                        modal: true,
                        postmethod: "form",
                        visible: true
                    });

                this.newProjectDialog.render(document.body);
                DOM.removeClass(this.newProjectDialog.innerElement, "hidden");
            }

            this.newProjectDialog.show();
        },

        /**
         *
         */
        _activeFilters: {},

        /**
         *
         */
        columns: [
            {
                formatter: BV.page.KDUProjectList.formatFieldProsjektnavn,
                key: "fieldProsjektnavn",
                label: "Prosjektnavn",
                minWidth: 300,
                sortable: true
            },
            {
                key: "fieldLokasjon",
                label: "Lokalisert i",
                sortable: true,
                width: 185
            },
            {
		formatter: BV.page.KDUProjectList.formatModifiedDate,
                key: "modifiedDate",
                label: "Sist endret",
                sortable: true,
                width: 95
            }

        ],

        /**
         *
         */
        dataSource: null,

        /**
         *
         */
        dataTable: null,

        /**
         *
         */
        paginator: null,

        /**
         *
         */
        rowsPerPage: 15,

        /**
         *
         */
        schema: {
            resultsList: "allProjects"
        },

        /**
         * Reference to "New Project pop-up dialog"
         */
        newProjectDialog: null
    };


    // Page initialisation

    Event.addListener(window, "load", function() {
		
        BV.page._CurrentPage = new BV.page.KDUProjectList(BV.page._Data);
    });

})();
