﻿/// <reference path="~/Standard/Core/Javascript/Relational.Standard.Core.js" />
/// <reference path="~/Standard/Core/Javascript/jquery.js" />

(function ($) {

    $.fn.facetCheckboxlistFilter = function (options) {

        this.each(function () {

            var defaults = {}; // set defaults in vb
            var config = $.extend(defaults, options);

            // NAMED ELEMENTS

            var self = this, $self = $(this);
            var $facetSearch = $self.parents(".FacetSearchContainer");
            var facetSearch = $facetSearch[0];
            var $checkboxListContainer = $("div.CheckboxListContainer", self);
            var $checkboxListTarget = $("div.CheckboxListTarget", self);
            var $checkboxListTemplate = $("script.CheckboxListTemplate", self);
            var $showFilterButton = $("a.ShowFilterButton", self);
            var $clearFilterButton = $("a.ClearFilterButton", self);
            var $filterTextboxContainer = $("div.FilterTextboxContainer", self);
            var $filterTextbox = $("input.FilterTextbox", self);
            var $clearFilterTextboxButton = $("a.ClearFilterTextboxButton", self);
            var $parentTabPanels = $("div.TabPanel").has($self);
            var $checkboxContainers;

            // WIRE UP EVENTS

            $self
                .bind("clear", clear)
                .bind("displayState", displayState)
                .bind("dataBind", dataBind)
                .bind("dataBound", dataBound)
                .bind("stateChanged", triggerSearch)
                .data("ready", true);
            $clearFilterButton.bind("click", clearFilterButton_Click);
            $showFilterButton.bind("click", showFilterButton_Click);
            $filterTextbox.keyup(filterTextbox_Keyup);
            $clearFilterTextboxButton.click(clearFilterTextboxButton_Click);

            // Watch for hash changes, which may change my visibility
            $(window).bind('hashchangeComplete', checkDataBound)

            // PUBLIC VARIABLES

            self.dataBound = true; // we come databound from the server, so don't need this any more

            // PUBLIC FUNCTIONS

            self.getId = config.id;
            self.getTitle = config.title;

            self.getState = function () {
                var checkedItems = [];
                $checkboxListTarget.find("input:checkbox:checked").each(function () {
                    checkedItems.push(this.value);
                });
                return checkedItems;
            }

            self.restoreState = function (state) {
                if (state) {
                    $.each(state.filters, function (i, filterState) {
                        // Find the state entry corresponding to this filter
                        if (filterState.id == config.id) {
                            // Check all checkboxes with the values specified
                            $.each(filterState.value, function (j, value) {
                                markChecked(value);
                            }) // each
                        } // if 
                    }) // each
                    $self.trigger("postStateChanged");
                } // if
            } // restoreState

            // PRIVATE FUNCTIONS

            function initializeFilterTextbox() {
                $checkboxContainers = $("div.CheckboxContainer", $checkboxListTarget);
                if (config.filterTextboxThreshold > 0 && $checkboxContainers.length > config.filterTextboxThreshold) {
                    $filterTextboxContainer.show();
                    $filterTextbox.val("");
                    // Removed call to $.watermark (11/15/2011)
                }
            }

            // EVENT HANDLERS

            function filterTextbox_Keyup(event) {
                // Filter visible checkboxes according to what's been typed in
                var s = $.fn.escapeRegex($filterTextbox.val());
                $checkboxContainers.each(function () {
                    var $checkboxContainer = $(this);
                    var $label = $checkboxContainer.find("label");
                    var $labelText = $label.find("strong");
                    var labelText = $label.attr("title");
                    var $checkbox = $checkboxContainer.find("input:checkbox");
                    var sRegex = new RegExp("\\b(" + s + ")", "i");
                    if (labelText.match(sRegex) || $checkbox.is(":checked")) {
                        $checkboxContainer.show();
                        $labelText.html(labelText.replace(sRegex, '<b>$1</b>'));
                    } else {
                        $checkboxContainer.hide();
                        $label.find("strong").text(labelText);
                    }
                });
            }

            function displayState(event, state) {
                dataBind(event, state);
                if (event) event.stopPropagation();
            }

            function dataBind(event, state) {
                // reset dataBound so list will refresh if displayed
                if (hasState(state) == true) {
                    // make sure I'm visible if I have any checkboxes checked (e.g. from a cookie)
                    showFilter();
                }
                // Ensure at least the filter container is visible or the :visible condition will always be false (after $self.hide() has been called once)
                $self.show();
                if ($checkboxListContainer.is(":visible") == false) {
                    // hide filter if no checkboxes would be displayed (e.g. none have an ItemCount > 0)
                    if (hasNoVisibleCheckboxes()) {
                        $self.hide();
                    }

                    // No point in loading if not visible
                    $self.data("ready", true);
                    // Clear our databound flag so we'll re-databind when we become visible
                    self.dataBound = false;
                } else {
                    disable();
                    //$r.showProgress(config.id);
                    // Get checkbox values from server
                    $.ajax({
                        url: $r.cleanHref(window.location),
                        type: "POST",
                        data: {
                            containerId: self.id,
                            action: "populate",
                            state: JSON.stringify(state),
                            facetSearchSourceView: config.facetSearchSourceView
                        },
                        success: function (msg) {
                            if (msg && msg.length > 0) {
                                $checkboxListTarget.html(msg);
                                wireUpCheckboxes();
                            } else {
                                $self.hide();
                            };
                            if (state) {
                                self.restoreState(state)
                            };
                            enable();
                            $self.trigger("dataBound");
                        }, // success
                        error: function (XMLHttpRequest, textStatus, errorThrown) {
                            $r.showError(XMLHttpRequest, errorThrown);
                            $checkboxListTarget.html("Error: " + errorThrown + ' ' + textStatus);
                            $r.hideProgress(config.id);
                        } // error
                    }); // ajax
                }
                if (event) event.stopPropagation();
            } // dataBind


            function disable() {
                $self
                    .data("ready", false)
                    .find("input").attr('disabled', 'disabled').end()
                    .dim();
            }

            function enable() {
                $self
                    .data("ready", true)
                    .find("input").removeAttr('disabled').end()
                    .unDim();
            }


            function wireUpCheckboxes() {
                $checkboxListTarget.find("input:checkbox").unbind("click.facetSearch").bind("click.facetSearch", checkbox_Click);
                if ($checkboxListTarget.find("input:checkbox").length == 0) {
                    $checkboxListTarget.html("<p>No matches.</p>");
                } else {
                    if (config.minSelections == 1) $checkboxListTarget.find("input:checkbox:first").addClass("{facetRequireOneCheck:true}");
                    $self.show()
                };
                // hide filter if no checkboxes would be displayed (e.g. none have an ItemCount > 0)
                if (hasNoVisibleCheckboxes()) {
                    $self.hide();
                } else {
                    $self.show();
                }
            }

            function dataBound(event) {
                $self
                    .data("ready", true)
                    .find("*").removeAttr('disabled');
                initializeFilterTextbox();
                self.dataBound = true;
                if (event) {
                    event.stopPropagation();
                    event.preventDefault();
                }
            }

            function checkbox_Click(event) {
                // Search
                triggerSearch();
                if (event) event.stopPropagation();
            }

            function clearFilterButton_Click(event) {
                if ($checkboxListTarget.find("input:checkbox:checked").length > 0) {
                    // Uncheck all checkboxes
                    clear();
                    // Search
                    triggerSearch();
                }
                if (config.minSelections == 0) {
                    // Hide checkboxes, show "narrow by" button (only if a selected from this list isn't required)
                    // Hiding this checkboxes when they are required would not allow the error to be visible
                    $checkboxListContainer.hide();
                    $showFilterButton.show();
                }
                $self.trigger("filterCleared");
                if (event) event.preventDefault();
            }

            function clearFilterTextboxButton_Click(event) {
                $filterTextbox.val("");
                filterTextbox_Keyup();
                if (event) event.preventDefault();
            }

            function clear(event) {
                $checkboxListTarget.find("input:checkbox").attr("checked", false);
                if (event) {
                    event.stopPropagation();
                    event.preventDefault();
                }
            }

            function showFilterButton_Click(event) {
                showFilter();
                checkDataBound();
                if (event) event.preventDefault();
            }

            function showFilter() {
                $checkboxListContainer.show();
                $showFilterButton.hide();
            }

            function hideFilter() {
                $checkboxListContainer.hide();
                $showFilterButton.show();
            }

            function triggerSearch() {
                // Tell our wrapper to perform search
                var t = setTimeout(function () {
                    $facetSearch.trigger("stateChanged")
                }, 1); // This is fired off asynchronously so that other stuff, like the checkbox getting checked, happens without a delay
            }

            // PRIVATE 

            function checkDataBound() {
                if ($checkboxListContainer.is(":visible") == true && self.dataBound == false) {
                    $self.trigger("dataBind", [facetSearch.getState()]);
                };
            }

            function hasState(state) {
                // Returns true if any of our checkboxes are checked
                var result = false;
                if (state) {
                    $.each(state.filters, function (i, filterState) {
                        if (filterState.id == config.id && filterState.value && filterState.value.length > 0) result = true;
                    })
                }
                return result;
            } // restoreState

            function markChecked(value) {
                // Finds the checkbox with the given value or text and checks it
                $("input:checkbox[value=" + value + "]", $checkboxListContainer).attr("checked", true)
                $("input:checkbox[title=" + value + "]", $checkboxListContainer).attr("checked", true)
                showFilter();
            }

            function checkQueryString() {
                // Allow values to be set from the querystring (on first load)
                // e.g. ?Sector=1
                var queryValue = $.query.get(config.id);
                if (queryValue) {
                    // The querystring has a value for us; select that value
                    clear();
                    markChecked(queryValue);
                    triggerSearch();
                }
            }

            function hasNoVisibleCheckboxes() {
                var $visibleContainers = $("div.CheckboxContainer:not(.Hidden)", $checkboxListTarget);
                return $visibleContainers.length == 0;
            }

            function wireUpResizable() {
                $('div._Resizable').resizable({
                    handles: 's',
                    minHeight: '100',
                    maxHeight: '500',
                    resize: function (event, ui) {
                        var newHeight = this.offsetHeight;
                        $("div.ScrollVertical", this)
                            .css("max-height", "500px")
                            .css("height", newHeight - 10);
                    }
                });
            }

            // INITIALIZE

            $.validator.addMethod(
                "facetRequireOneCheck", function (value, element) {
                    if ($(element).hasClass('NoValidate')) return true;
                    return ($(element).parents('.CheckboxListTarget').find('input:checked').length > 0);
                },
                "Please choose at least one option."
            ); // facetRequireOneCheck

            var state = facetSearch.restoreState();
            self.restoreState(state);
            //$self.trigger("dataBind", [state]);
            wireUpCheckboxes();
            initializeFilterTextbox();
            checkQueryString();
            wireUpResizable();

        }); // each

        return this; // don't break the chain

    }; // $.fn.facetFilter

})(jQuery);



