﻿// ----------------------------------------------------------------------------------
//  In charge of doing actual searches. Enter criterias using various methods and 
//  call DoSearch(). Searchcontroller will then call you back when result is ready.
//  Parameters:
//      name:               A name you think up. 
//      searchEngineUrl:    Basic url to search engine
// ----------------------------------------------------------------------------------
function SearchController(name) {
    this.name = name;
    this.sortField = null;
    this.sortDir = null;
    this.page = 0;
    this.pageSize = 10;
    this.freetext = "";
    this.minSalesPrice = 0;
    this.maxSalesPrice = 9999;
    this.MultiLevelCheckboxCriterias = new Array();
    this.MultiCheckboxCriterias = new Array();
    this.pubBeforeField = null;
    this.pubBeforeValue = null;
    this.pubAfterField = null;
    this.pubAfterValue = null;
    this.keyword = null;
    this.sortValue = '';
    this.facets = new Array();
    this.firstPageHit = true;
    this.contextId = null;
    this.contextLanguage = null;

    var self = this;

    // Numbers of results to show per page.
    this.SetPageSize = function(pagesize) {
        this.pageSize = pagesize;
    }

    // Current page in search result. Starts from zero.
    this.SetPage = function(page) {
        this.page = page;
    }

    this.ClearAllCriteria = function() {
        this.criteriaSize = null;
        this.criteriaBrands = null;
        this.freetext = "";
        this.MultiLevelCheckboxCriterias = new Array();
        this.MultiCheckboxCriterias = new Array();
        this.minSalesPrice = 0;
        this.maxSalesPrice = 9999;
        this.sortField = null;
        this.sortDir = null;
        this.page = 0;
        this.facets = new Array();
        //this.useQSForSearch = true; //add if needed
    }

    this.SetCriteriaKeyword = function(name, keyword) {
        self.keyword = keyword;
    }


    // Enter criteria from a MultiCheckbox. Name is the name of the MultiCheckbox.
    this.SetMultiCheckboxCriteria = function(name, controlItemState) {
        //debug("SearchController(" + this.name + ").SetControlMultiCheckboxCriteria()" + criteria.length);
        this.page = 0;
        self.MultiCheckboxCriterias[name] = controlItemState;
    }

    // Enter criteria from a MultiLevelCheckbox. Name is the name of the MultiLevelCheckbox.
    this.SetMultiLevelCheckboxCriteria = function(name, criteria) {
        //debug("SearchController(" + this.name + ").SetControlMultiLevelCheckboxCriteria()");
        self.MultiLevelCheckboxCriterias[name] = criteria;
        //debug("gemt under: " + name);
        this.page = 0;
        //debug("~SearchController(" + this.name + ").SetControlMultiLevelCheckboxCriteria()");
    }

    this.SetCriteria_PublicationDate = function(name, pubBeforeField, pubBeforeValue, pubAfterField, pubAfterValue) {
        //alert("searchcontroller pub '"+pubBeforeField+"'");
        self.pubBeforeField = pubBeforeField;
        self.pubBeforeValue = pubBeforeValue;
        self.pubAfterField = pubAfterField;
        self.pubAfterValue = pubAfterValue;
    }

    // Freetext from user. Example: "jeans".
    this.SetFreetextCriteria = function(text) {
        this.freetext = text;
        this.page = 0;
    }

    // Facet criterias from user.
    this.SetFacetCriterias = function(facets) {
        this.facets = facets;
        this.page = 0;
    }

    // Set MultiCheckboxCriterias from facet criterias from user
    this.SetMultiCheckboxCriterias = function(facets) {
        for (var i = 0; i < facets.length; i++) {
            var facetFE = facets[i];
            var controlItemState = new Object();
            var name = decodeURIComponent(facetFE.FieldName);

            controlItemState.controlElementInfos = new Array();
            controlItemState.facetType = facetFE.FacetType;
            controlItemState.allFacetQueries = facetFE.FacetQueries;

            for (var j = 0; j < facetFE.FacetFields.length; j++) {
                var info = new Object();
                info.name = decodeURIComponent(facetFE.FacetFields[j].FieldName);
                controlItemState.controlElementInfos.push(info);
            }
            self.MultiCheckboxCriterias[name] = controlItemState;
        }
    }


    // The price range to include in search.
    this.SetMinMaxPrice = function(min, max) {
        this.minSalesPrice = min;
        this.maxSalesPrice = max;
    }

    this.SetSortCriteria = function(sortField, dir) {
        //debug("SearchController[" + this.name + "](sortField=" + sortField + ", dir=" + dir);
        //this.page = 0;
        this.sortField = sortField;
        this.sortDir = dir;
    }

    this.SetSortCriteria2 = function(value) {
        //debug("SearchController[" + this.name + "](sortField=" + sortField + ", dir=" + dir);
        //this.page = 0;
        this.sortValue = value;
    }

    // create request from all criteria and send request to search engine. callback parameter is 
    // the method you want to be called with searchresult.
    this.DoSearch = function(callback) {
        var _this = this;
        var index = location.href.indexOf("#");

        if (CommonHelper.getUrlVars()["qs"] != null && this.firstPageHit == true && index <= 0) {
            this.SetFreetextCriteria(decodeURIComponent(CommonHelper.getUrlVars()["qs"]));
        }

        var sq = this.freetext != "" ? encodeURIComponent(this.freetext) : "";
        var fqs = new Array();

        for (var key in self.MultiCheckboxCriterias) {
            var facetFE = new Object();
            var controlItemState = self.MultiCheckboxCriterias[key];
            facetFE.FacetType = controlItemState.facetType;
            facetFE.FieldName = encodeURIComponent(key);
            facetFE.FacetFields = new Array();
            for (var i = 0; i < controlItemState.controlElementInfos.length; i++) {
                var facetFieldFE = new Object();
                facetFieldFE.FieldName = encodeURIComponent(controlItemState.controlElementInfos[i].name);
                facetFieldFE.Count = 0;
                facetFE.FacetFields.push(facetFieldFE);
            }
            facetFE.FacetQueries = controlItemState.allFacetQueries;
            fqs.push(facetFE);
        }

        var searchService = new SearchService();
        searchService.ajax.success = function(s) {
            callback(s, _this);
        }

        searchService.ajax.error = function() {
            alert('error!');
        }

        var searchQuery = {
            QueryText: sq,
            FilterQueries: fqs,
            PageNumber: _this.page,
            PageSize: _this.pageSize,
            FacetNames: facetNames,
            Sort: encodeURIComponent(_this.sortValue),

            toPersistState: function(object) {
                var serializedObject = JSON.stringify(object);
                var encodedQuery = encode64(serializedObject);
                window.location = '#' + encodedQuery;
            },

            fromPersistState: function() {
                var index = location.href.indexOf("#");
                if (index > 0) {
                    var encodedQuery = location.href.substring(index);
                    var decodedQuery = decode64(encodedQuery);
                    var serializedObject = JSON.parse(decodedQuery);
                    this.fromObject(serializedObject);
                }
            },

            toObject: function() {
                var query = new Object();
                query.QueryText = this.QueryText;
                query.FilterQueries = this.FilterQueries;
                query.PageNumber = this.PageNumber;
                query.PageSize = this.PageSize;
                query.FacetNames = this.FacetNames;
                query.Sort = encodeURIComponent(this.Sort);

                return query;
            },

            fromObject: function(query) {
                this.QueryText = query.QueryText;
                this.FilterQueries = query.FilterQueries;
                this.PageNumber = query.PageNumber;
                this.PageSize = query.PageSize;
                this.FacetNames = query.FacetNames;
                this.Sort = query.Sort;
            }
        }

        if (!this.firstPageHit && index <= 0) {
            //original search was based on qs and the url# was therefor not set. Now the search has changed and url# needs to be set
            //console.log('persist 1. Persist after initial qs use');
            searchQuery.toPersistState(searchQuery);
        }
        else if (this.firstPageHit && index <= 0) {
            //first search on qs, do nothing
            //console.log('persists 2. First search on qs');
        }
        else if (this.firstPageHit && index > 0) {
            //browser back or page refresh
            searchQuery.fromPersistState();
            this.SetMultiCheckboxCriterias(searchQuery.FilterQueries);
        }
        else if (!this.firstPageHit && index > 0) {
            //console.log('persists 4. Normal persist. Url# exists and it isnt an initial search');
            searchQuery.toPersistState(searchQuery);
        }

        //the individual controls recreate search criteria from these variables now the that state of the page isnt enough anymore.
        var tmpPage = this.page;
        this.SetFreetextCriteria(decodeURIComponent(searchQuery.QueryText));
        this.SetSortCriteria2(decodeURIComponent(searchQuery.Sort));
        this.SetFacetCriterias(searchQuery.FilterQueries);
        this.page = tmpPage;

        this.firstPageHit = false;
        searchQuery.ContextId = this.contextId;
        searchQuery.ContextLanguage = this.contextLanguage;

        searchService.GetSearch(searchQuery);
    }
}   
