

var AjaxSearch = new Class ({

    initialize: function(instance) {

        this.self = instance;
        this.ajaxUrl            = '/Shop/?action=ajaxSearch';

        this.searchTimer        // Timer holder for the searchfunction (for price changes)

        // Form element collection
        this.formElements = new Array;

        // Keywords and category selection values
        this.keywords           = '';
        this.mainCategoryId     = '';

        // Pricerange values
        if ( $('filterMinPrice') )
            this.minPrice           = $('filterMinPrice').value;
        else
            this.minPrice           = '';


        if ( $('filterMaxPrice') )
            this.maxPrice           = $('filterMaxPrice').value;
        else
            this.maxPrice           = '';

        this.selectedMinPrice   = this.minPrice;
        this.selectedMaxPrice   = this.maxPrice;

        this.priceModified      = false;

        // Manufacturers
        this.manufacturers             = new Array();
        this.manufacturersPopupState   = false;

        // Sub sub category (results per category
        this.subSubCategory            = '';

        // Specs
        this.specsSearch    = new Array();
        this.specs          = new Array();

        this.lastSpecRowID  = 0;

        // Add javascript events to form elements
        this.addEvents();

        // Get the currently set priceraneg
        this.getPriceRange();

        // Setup the brand selection div
        if ( $('searchManufacturerSelectPopup') ) {
            this.formElements['searchManufacturerSelectPopup'] = $('searchManufacturerSelectPopup')
            this.formElements['searchManufacturerSelectPopup'].setStyle('opacity',0)
            this.formElements['searchManufacturerSelectPopup'].setStyle('display', 'block')
        }

        setPriceSlider(this.minPrice,this.maxPrice,this.selectedMinPrice, this.selectedMaxPrice);

    },

    addEvents: function() {

        // Keywords input screen
        if ( $('searchKeywords') )  {
            this.formElements['searchKeywords'] = $('searchKeywords');

            this.formElements['searchKeywords'].addEvent('blur',
                function(element) {
                    ajaxSearch.setKeywords($('searchKeywords').value);
                }.bind(this)
            )

            this.formElements['searchKeywords'].addEvent('keydown',
                function(event) {
                    if ( event.key=='enter') {
                        ajaxSearch.setKeywords($('searchKeywords').value);
                        return false;
                    }
                }.bind(this)
            )

        }


        // Category select box
        if ( $('searchMainCategory') )  {
            this.formElements['searchMainCategory'] = $('searchMainCategory');
            this.formElements['searchMainCategory'].addEvent('change',
                function(element) {
                    ajaxSearch.setMainCategory($('searchMainCategory').value);
                }.bind(this)
            )
        }

        // Manufacturer selection popup
        if ( $('searchManufacturerSelect') )  {
            this.formElements['searchManufacturerSelect'] = $('searchManufacturerSelect');
            this.formElements['searchManufacturerSelect'].addEvent('click',
                function(element) {
                    this.setToggleManufacturerSelectPopup();
                }.bind(this)
            )
            this.formElements['searchManufacturerSelect'].setStyle('cursor' , 'pointer');
        }

        if ( $('searchManufacturerSelectPopup') ) {
            this.formElements['searchManufacturerSelectPopup'] = $('searchManufacturerSelectPopup');
            this.formElements['searchManufacturerSelectPopup'].addEvent('mouseleave',
                function() {
                    this.setToggleManufacturerSelectPopup(0);
                }.bind(this)
            )
        }

    },

    addEvent: function( elementId, event, func ) {
        $(elementId).addEvent(event , function() { func } )
    },

    /**
     * Store the entered keywords in this.keywords
     */
    setKeywords: function(keywordString) {

        if ( keywordString != this.keywords) {

            this.keywords = keywordString

            // Clear the other options, since keywords searches go over all categories and such
            this.mainCategoryId = ''

            this.manufacturers = new Array()

            this.subSubCategory            = ''

            this.specs      = new Array();
            this.specSearch = new Array();

            this.selectedMinPrice = 0;
            this.selectedMaxPrice = 999999999;


            // Perform the search
            this.search()

        }

    },

    /**
     * Store the selected main category in this.mainCategoryId
     */
    setMainCategory: function(categoryId) {

        if ( categoryId != this.mainCategoryId ) {

            // When the MainCategory is changed, the specsearch becomes invalid
            // Clear the specs and specsearch
            this.specs      = new Array();
            this.specSearch = new Array();

            // Clear prices
            this.selectedMinPrice = 0;
            this.selectedMaxPrice = 999999999;

            this.mainCategoryId = categoryId;

            // Perform the search
            this.search()
        }

    },

    /**
     * Read the pricerange from the hidden filterMinPrice and filterMaxPrice fields.
     */
    getPriceRange: function() {

        if ( $('filterMinPrice') )
            this.minPrice   =   $('filterMinPrice').value;

        if ( $('filterMaxPrice') )
            this.maxPrice   =   $('filterMaxPrice').value;

    },

    /**
     * Set the min price, this function is called by the slider class
     */
    setMinPrice: function(minPrice, doSearch) {

        doSearch = doSearch || false;

        if ( minPrice != this.minPrice ) {

            clearTimeout(this.searchTimer)
            if ( doSearch ) {
                this.searchTimer = setTimeout( "ajaxSearch.search('priceSlider'); ", 1000);
            }
            $('filterMinPrice').set('value', minPrice)
            this.selectedMinPrice = minPrice

            this.priceModified = true

        }

    },


    /**
     * Set the min price, this function is called by the slider class
     */
    setMaxPrice: function(maxPrice, doSearch) {

        doSearch = doSearch || false;

        if ( maxPrice != this.maxPrice ) {

            clearTimeout(this.searchTimer)
            if ( doSearch ) {
                this.searchTimer = setTimeout( "ajaxSearch.search('priceSlider');", 1000);
            }
            $('filterMaxPrice').set('value', maxPrice)
            this.selectedMaxPrice = maxPrice

            this.priceModified = true

        }

    },




    /**
     * Show or hide the brand selection popup
     */
    setToggleManufacturerSelectPopup: function(state) {

        if ( this.manufacturersPopupState || state == 0) {

            $('searchManufacturerSelectPopup').fade(0)

            // Save the manufacturers when the popup closes
            this.setManufacturers()

            this.manufacturersPopupState = false;

        } else if ( !this.manufacturersPopupState || state == 1) {

            $('searchManufacturerSelectPopup').fade(1)
            this.manufacturersPopupState = true;

        }

    },

    /**
     * Set the manufacturers array and do search if it changed
     */
    setManufacturers: function () {

        // Get the currently set manufacturers
        manufacturers   = new Array();
        manufacturerLabels = new Array();

        manufacturerCheckboxes = $('searchManufacturerSelectPopup').getElements('input[name^=manufacturers]')
        for ( var i = 0; i < manufacturerCheckboxes.length; i++ ) {
            if ( i == 0 ) selectedManufacturerString = "";
            if(manufacturerCheckboxes[i].checked){
                manufacturers[manufacturers.length] = manufacturerCheckboxes[i].value;

                // Get the contents of the label belonging to this checkbox
                labelElements = manufacturerCheckboxes[i].getParent().getElements('label')
                manufacturerLabels[manufacturers.length] = labelElements[0].innerHTML;

            }
        }

        if ( !manufacturers.compare(this.manufacturers) ) {
            this.manufacturers = manufacturers

            // The first item is empty, and we dont want it in the comma seperated list, so we shift it.
            manufacturerLabels.shift();

            // Show the list of selected manufacturers in the searchSelectedmanufacturers span

            if ( manufacturerLabels.length != 0 ) {
                $('searchSelectedManufacturers').set('html', 'Filter op: ' + manufacturerLabels.join(', ') )
            } else {
                $('searchSelectedManufacturers').set('html', 'Filter op: <geen>')
            }

            // Perform the search
            this.search('searchManufacturerSelectPopup')
        }



    },

    /**
     * Set the subcategory
     */
    setSubSubCategory: function(subSubCategoryId) {

        subSubCategoryId = subSubCategoryId || ''

        // When the subsub category is changed, the specsearch becomes invalid
        // Clear the specs and specsearch
        this.specs      = new Array();
        this.specSearch = new Array();

        // Clear prices
        this.selectedMinPrice = 0;
        this.selectedMaxPrice = 999999999;

        // Store this subCategory
        this.subSubCategory = subSubCategoryId

        // Perform the search
        this.search()

    },


    /**
     * Calls addspecSearchRow to add a new row for specsearching, just a stub to add functionality to if needed.
     */
    addSpecSearch: function (spec, specValue) {
        this.addSpecSearchRow(this.lastSpecRowID+1)
    },

    /**
     * Adds a row to the specsearch and changes the previous row so that the add row button changes into a remove row
     */
    addSpecSearchRow: function (rowID) {

        if ( !$('searchSpecsRow_' + this.lastSpecRowID) ) {
            alert('Cant find last row')
        } else {

            lastSpecRow = $('searchSpecsRow_'+this.lastSpecRowID);

            newSpecRowElement = new Element('tr', {'class':'searchSpecsRow', 'id': 'searchSpecsRow_'+rowID})


            // If this is the first row, we need the label so we add a TD with "Specificaties" else an empty td is injected
            if ( rowID == 1 ) {
                var delimiterRow = new Element('tr', { 'id': 'specSearchDelimiter' } )
                var delimiterTd  = new Element('td', {'colspan': 2}).injectInside(delimiterRow)
                var delimiterDiv = new Element('div', {'class':'delimiter'}).injectInside(delimiterTd)
                delimiterRow.injectBefore(lastSpecRow)

                new Element('td', { 'html': 'Specificaties:'} ).injectInside(newSpecRowElement)
            } else {
                new Element('td').injectInside(newSpecRowElement)
            }

            /**
             *  Add the specSearch select to the row
             */
            newSpecSearchSelectTD = new Element('td').injectInside(newSpecRowElement)

            // If this is not the first row, we want a top padding of 4px
            if ( rowID != 1 ) newSpecSearchSelectTD.setStyle('padding-top', '4px')


            newSpecSearchSelect = new Element('select', { 'class':'searchSpecsSelect', 'id': 'searchSpecsSelect_'+rowID }).injectInside(newSpecSearchSelectTD);

            // Add the default option to the specSearch select
            new Element('option', {'html': 'Selecteer specificatie', 'value': ''} ).injectInside(newSpecSearchSelect)

            /**
             * Add the available specs based on the return data of the this.search() method. This return data
             * is stored in this.specValues
             */
            $each(this.specs, function(value,index) {
                new Element('option', {'html': value.specLabel, 'value': value.specID} ).injectInside(newSpecSearchSelect)
            })


            // The second dropdown in the specsearch row should be enabled when the first box has any value other then ""
            newSpecSearchSelect.addEvent('change',
                function() {

                    var specSelect = $('searchSpecsSelect_' + rowID)
                    var selectedSpec = specSelect.value;

                    var valueSelect = $('searchSpecsValue_' + rowID)

                    if ( specSelect.value != "" ) {

                        // Clear the contents of the searchSpecsValue on this row, just incase we just switched  specs in the dropdown
                        valueSelect.empty();

                        /**
                         * Fill the searchSpecsValue dropdown with valid options, depending on the selected spec
                         */

                        // First add the empty default value
                        new Element('option', {'value': '', 'html': 'Geen voorkeur'} ).injectInside(valueSelect)

                        // Now add all the values belonging to the selected spec using this.specsValues
                        $each(this.specs, function(value, index) {

                            if ( value.specID == selectedSpec) {

                                $each(value.specValues, function(specValue, index) {

                                    // Some values have 'odd' names, we need to replace them with readable values
                                    if ( specValue == '$Y' ) {
                                        specValueName = 'Ja'
                                    } else if ( specValue == '$N' ) {
                                        specValueName = 'Nee'
                                    } else {
                                        specValueName = specValue
                                    }

                                    new Element('option', {'value': specValue, 'html': specValueName} ).injectInside(valueSelect)
                                })

                            }
                        })



                        // Enable the searchSpecsValue dropdown
                        valueSelect.disabled = false

                    } else {
                        valueSelect.selectedIndex = 0
                        valueSelect.disabled = true
                    }
                }.bind(this)

            )



            /**
             *  Add the specValue Value to the row
             */
            newSpecSearchValue = new Element('select', { 'class':'searchSpecsValue', 'id': 'searchSpecsValue_'+rowID }).injectInside(newSpecSearchSelectTD);
            newSpecSearchValue.set('disabled', 'true')

            // Add the default option to the specValue Value
            new Element('option', {'html': 'Geen voorkeur', 'value': ''} ).injectInside(newSpecSearchValue)

            /**
             * Add the add new row button to the row
             */
            newSpecSearchAdd = new Element('a', {'href': 'javascript:void(0)', 'class': 'searchSpecsAdd', 'id': 'searchSpecsAdd_'+rowID } ).injectInside(newSpecSearchSelectTD);

            // The + icon in the spec search row should trigger the addSpecSearch method, but only when the first 2 select boxes are filled
            newSpecSearchAdd.addEvent('click',

                function () {
                    if ( $('searchSpecsSelect_' + rowID ).value == "" || $('searchSpecsValue_' + rowID).value == "" ) {
                        return false;
                    } else{
                        this.addSpecSearch($('searchSpecsSelect_' + rowID).value, $('searchSpecsValue_' + rowID).value)
                    }
                }.bind(this)
            )

            /**
             * Inject the Row after the last current visible row.
             */
            newSpecRowElement.injectAfter(lastSpecRow)


            /**
             * Change the button of the previous row from addrow to delete row. (if it exists)
             */
            if ( $('searchSpecsAdd_' + this.lastSpecRowID) ) {

                $('searchSpecsAdd_' + this.lastSpecRowID).removeEvents();
                $('searchSpecsAdd_' + this.lastSpecRowID).className = "searchSpecsDel";

                lastSpecRowID = this.lastSpecRowID

                // Add click event to the old button to remove that row
                $('searchSpecsAdd_' + this.lastSpecRowID).addEvent('click',
                    function (event) {
                        this.removeSpecSearchRow(rowID-1)
                    }.bind(this)
                )

            }

            this.lastSpecRowID++;

        }

    },

    /**
     * Removes a row from spec search
     */
    removeSpecSearchRow: function(row) {
        if ( $('searchSpecsRow_' + row) ) {
            $('searchSpecsRow_' + row).destroy()
            return true
        }
        return false
    },

    /**
     * Removes the specs selection rows
     */
    clearSpecs: function() {
        var specRows = $(document.body).getElements('tr.searchSpecsRow')

        specCount = 0
        $each(specRows, function(row) {
            if ( row.id != "searchSpecsRow_0" ) {
                row.destroy();
            }
        })

        if ( $('specSearchDelimiter') ) {
            $('specSearchDelimiter').destroy();
        }

        // Reset the specrow counter
       this.lastSpecRowID  = 0
    },

    /**
     * Reads the specsearch objects and stores the data in this.specSearch
     */
    getSpecsSearchValues: function() {

        var specSearchValues = new Array
        var specRows = $(document.body).getElements('tr.searchSpecsRow')

        specCount = 0
        $each(specRows, function(row) {

            if ( row.getElement('.searchSpecsSelect') ) {
                spec        = row.getElement('.searchSpecsSelect').value
            } else {
                spec = "";
            }

            if ( row.getElement('.searchSpecsValue') ) {
                specValue = row.getElement('.searchSpecsValue').value
            } else {
                specValue = "";
            }

            if ( spec != "" && specValue != "" ) {

                specSearchValues[specCount] = new Array
                specSearchValues[specCount][0] = spec
                specSearchValues[specCount][1] = specValue
                specCount++;
            }



        })

        return specSearchValues;

    },


    /**
     * Search function
     * @param elementID ID of the element that should not be updated with the new information
     */
    search: function( skipUpdating ) {

        skipUpdating = skipUpdating || false

        keywords        = this.keywords || $('searchKeywords').value
        mainCategory    = this.mainCategoryId
        subSubCategory  = this.subSubCategory

        //console.log("this.minPrice: '" + this.minPrice + "'\nthis.selectedMinPrice: '" + this.selectedMinPrice )
        //console.log("this.maxPrice: '" + this.maxPrice + "'\nthis.selectedMaxPrice: '" + this.selectedMaxPrice )

        if ( this.priceModified && ( this.selectedMinPrice != this.minPrice || this.selectedMaxPrice != this.maxPrice ) ) {
            minPrice        = this.selectedMinPrice
            maxPrice        = this.selectedMaxPrice
        } else {
            minPrice        = 0
            maxPrice        = 999999999;
        }



        /* Get the selected manufacturerIDs */
        manufacturers   = this.manufacturers;

        // Get the spec search values
        if ( subSubCategory != '' ) {
            this.specSearch = this.getSpecsSearchValues()
        }

        // Build the ajax data string
        ajaxDataString =    '&ajaxaction=search'    +
                            '&keywords='            + keywords +
                            '&mainCategory='        + mainCategory +
                            '&subSubCategory='      + subSubCategory +
                            '&minPrice='            + minPrice +
                            '&maxPrice='            + maxPrice +
                            '&manufacturers='       + manufacturers

        ajaxRequest =   new Request({
                            url:        this.ajaxUrl + ajaxDataString,
                            data:       { 'specs' : this.specSearch },
                            method:     'get',
                            async:      true,
                            onRequest:  function() {
                                            $('searchPage').getElements( '.ajaxProgressIndicator' ).forEach( function( el ) {
                                              el.setStyle('display','block')
                                            });
                                        },
                            onComplete: function() {
                                            $('searchPage').getElements( '.ajaxProgressIndicator' ).forEach( function( el ) {
                                              el.setStyle('display','none')
                                            });
                                        },
                            onSuccess: function(response) {

                                response = JSON.decode(response)

                                // Update the main search categories
                                if ( skipUpdating != 'searchMainCategory' )
                                    $('searchMainCategory').set('html', response.mainCategoryHTML)

                                // Update the found categories
                                if ( skipUpdating != 'foundInCategoryList' )
                                    $('foundInCategoryList').set('html', response.resultsPerCategoryHTML)

                                if ( skipUpdating != 'priceSlider' ) {
                                    if ( response.minPrice && response.maxPrice ) {
                                        setPriceSlider(this.minPrice, this.maxPrice, this.minPrice, this.maxPrice, false);
                                        this.minPrice = response.minPrice
                                        this.maxPrice = response.maxPrice
                                        this.selectedMinPrice = response.minPrice
                                        this.selectedMinPrice = response.maxPrice
                                    }
                                }

                                // Update manufacturers
                                if ( skipUpdating != 'searchManufacturerSelectPopup' )
                                    $('searchManufacturerSelectPopup').set('html', response.manufacturersHTML )

                                // Update total
                                if ( skipUpdating != 'searchResultTotal' )
                                    $('searchResultTotal').set('html', response.total);

                                // If we have results, we show the results per category
                                if ( response.total > 0 ) {
                                    $$( '.foundInCategoryRows' ).forEach( function( el ) {
                                      el.setStyle('display','block')
                                    });

                                } else {
                                    $$( '.foundInCategoryRows' ).forEach( function( el ) {
                                      el.setStyle('display','none')
                                    });
                                }

                                if ( response.specs && response.specs.length > 0) {

                                    if ( JSON.encode(response.specs) != JSON.encode(this.specs) ) {
                                        this.specs = response.specs

                                        this.clearSpecs()
                                        this.addSpecSearch(this.lastSpecRowID)
                                    }

                                } else {

                                    // Clear the specs and specsearch
                                    this.specs      = new Array();
                                    this.specSearch = new Array();

                                    this.clearSpecs()
                                }

                                this.priceModified = false;
                                ajaxSearch.showResults(1);

                            }.bind(this)

                        })

        ajaxRequest.send();


    },

    showResults: function(page, perPage, orderBy, order) {

        page = page || 1
        perPage = perPage || 10

        orderBy = orderBy || 'name'
        order   = order || 'desc'

        ajaxDataString =    '&ajaxaction=getResults'    +
                            '&page='                    + page +
                            '&perpage='                 + perPage +
                            '&orderby='                 + orderBy +
                            '&order='                   + order


        ajaxRequest =   new Request({
                            url:        this.ajaxUrl + ajaxDataString,
                            method:     'get',
                            async:      true,
                            onRequest:  function() {
                                            $('searchPage').getElements( '.ajaxProgressIndicator' ).forEach( function( el ) {
                                              el.setStyle('display','block')
                                            });
                                        },
                            onComplete: function() {
                                            $('searchPage').getElements( '.ajaxProgressIndicator' ).forEach( function( el ) {
                                              el.setStyle('display','none')
                                            });
                                        },
                            onSuccess: function(response) {
                                $('searchResults').set('html',response)
                            }
                        })

        ajaxRequest.send();

    }

})



