﻿
// -------------------------------------------------------------------------------------------------------
//  Parameters
//      name:           Used to generate the id of divs and HTML controls 
//                      (other words will be added to create unique id's). 
//      headline:       Text shown at top of control.   
//      facetFieldObjPath: String containing the path in search result to facet. String is used to get 
//                      object using reflection. Path could be something like:  
//                      data.facet_counts.facet_fields.myfacet. The format of the facet is to be like this:
//                      Index 0: "¤Badeshorts|44¤bukser|21" (44 and 21 in this case being the id)
//                      Index 1: "193" (193 in this case representing number of items in this facet).
//                      ...
//      facetFilter:    The facet (which may be) used in Filter Query (example: data.responseHeader.params.fq). 
//                      This is used to determine which checkboxes should be checked.
// -------------------------------------------------------------------------------------------------------
function ControlMultiLevelCheckbox(name, headline, facetFieldObjPath, facetFilter) 
{
    this.headline = headline;       // Headline of control.
    this.name = name;     //MultiCheckboxLevel          
    this.checkboxPrefix = "mcbl_"; // First part of name of every checkbox in control.
    this.nameDiv = this.checkboxPrefix+name+"Div";      // Name of div that surrounds the control.
    this.headlineDivId = this.checkboxPrefix+"Headline_"+name+"Div";
    this.contentDivId = this.checkboxPrefix+"Content_"+name+"Div";
    this.criteriaListStatus = new Array();   
    this.userManipulated=false; // user has used control at some point.
    this.resetLinkDivId = this.checkboxPrefix+name+"_Reset";
    this.resetLinkId = this.checkboxPrefix+name+"_ResetLink";

    this.facetFieldObjPath = facetFieldObjPath;
    this.facetFilter = facetFilter;
    this.criteriaListStatus = new Array(); 
    this.logicOperator = "AND";
    var self = this;
    this.textAfterCount = "";
    this.checkboxPathArray=null;
    // ------------------------------------------------------------------------------
    // [x] Item A (2[insert text])
    // [ ] Item B (2[insert text])
    // ------------------------------------------------------------------------------
    this.SetTextAfterCount = function(text)
    {
        self.textAfterCount = text;   
    }

    // ------------------------------------------------------------------------------
    // Logic operator
    // AND  or   OR
    // ------------------------------------------------------------------------------
    this.SetLogicOperator = function(operatorText) {
        self.logicOperator = operatorText;
    }
    

    
    // ------------------------------------------------------------------------------
    //  Write HTML to page.
    // ------------------------------------------------------------------------------
    this.Render = function()
    {
    
        var temp="";  
        var criteria;
        
        // Outer div    
        temp += "<div id='"+this.nameDiv+"' class='ControlDiv MultiCheckbox'>";    
        
        temp += "<div id='"+this.headlineDivId+"' class='ControlHeadline'>";     
        temp += "<div class='FilterControlHeadlineText'>"+this.headline
        temp += "<div id='"+this.resetLinkDivId+"' class='ControlHeadlineReset'><a id='"+this.resetLinkId+"' href=''>nulstil</a></div>";
        temp += "<div class='breaker'></div>"
        temp += "</div></div>";

        temp += "<div id='"+this.contentDivId+"' class='ControlContent'>";     
        temp += "</div>";
                            
        // End outer div.
        temp += "</div>";
        
        // Write HTML to page. 
        document.write(temp);    
        
        // set height of containing div. This height is the relationshi
        //debug(jQuery("div#"+this.nameDiv).height() + " - " + jQuery("div#"+this.headlineDivId).height());
//        var headlineHeight = (jQuery("div#"+this.nameDiv).height() - jQuery("div#"+this.headlineDivId).height() )  ;
//        jQuery("div#"+this.contentDivId).height(headlineHeight);
        
        $jq(document).ready(function() 
        {
            $jq(document).bind('SearchResult', self.OnSearchResult);   
            $jq("#"+self.resetLinkId).bind("click", self.OnResetLinkClick);
        });      
                       
    }
    this.Render();
    
    // ------------------------------------------------------------------------------
    //  User clicked on reset link. Uncheck all checkboxes and do new search.
    // ------------------------------------------------------------------------------
    this.OnResetLinkClick = function()
    {
        self.userManipulated = false; 
        $jq("#"+self.resetLinkDivId).hide();
   
        for (i=0;i<self.criteriaListStatus.length;i++)
        {
            self.criteriaListStatus[i].selected = false;
            $jq("#"+self.criteriaListStatus[i].id).attr('checked', false);         
        } 

        fc.CriteriaChange_ControlMultiLevelCheckbox(self.name, self.criteriaListStatus, true); 
        return false;
    }
    
    // ------------------------------------------------------------------------------
    //  Search controller will receive all relevant events from this 
    //  control.
    // ------------------------------------------------------------------------------     
    this.RegisterAsTrigger = function(searchController)
    {
        fc.RegisterTrigger(self.name, searchController);
    }
    
        
    // ------------------------------------------------------------------------------
    //  Subscribe to event from a searchcontroller.
    // ------------------------------------------------------------------------------         
    this.SubscribeEvent = function(searchController, eventName, callback)
    {
        fc.SubscribeEvent(this, searchController, eventName, callback);
    }
    
    this.SubscribeEvents = function(searchController)
    {
        fc.SubscribeEvent(self, searchController, "SearchResult", self.OnSearchResult); 
    }
    
    this.ShowResetLink = function()
    {
        $jq("#"+self.resetLinkDivId).show();
    }
    
    this.HideResetLink = function()
    {
        $jq("#"+self.resetLinkDivId).hide();
    }
       
    // ------------------------------------------------------------------------------
    //  When a checkbox is clicked we must sens criteria change to flowcontroller.
    // ------------------------------------------------------------------------------  
    this.CheckboxClicked = function(event)
    {
        debug("MultiLevelCheckbox["+self.name+"].CheckboxClicked()");
        DebugAddTab()
        //alert("multi level checkbox clicked "+event.data.cbId); 
        
        for (i=0;i<=self.criteriaListStatus.length;i++)
        {                              
            if (self.criteriaListStatus[i].id == event.data.cbId)
            {
                //var path = $jq('input#'+event.data.cbId).attr('path'); // does not work in IE7
                var path = self.checkboxPathArray[event.data.cbId];
                //alert("path: "+path);
                
              
                var isChecked = $jq("input[id="+event.data.cbId+"]").attr('checked');   //$jq('input#'+event.data.cbId).attr('checked'));
                
                if ( isChecked == true)  
                {
                    self.userManipulated = true;
                    self.ShowResetLink();
        
                    self.criteriaListStatus[i].selected = true;
                    //alert("control '"+self.name+"' had checkbox '"+event.data.cbId+"' checked");
                }   
                else
                {
                    //alert("control '"+self.name+"' had checkbox '"+event.data.cbId+"' unchecked");
                    self.criteriaListStatus[i].selected = false;
                    
                    // If all checkboxes are unchecked then make sure that we do not show reset link.
                    for(var i=0; i<self.criteriaListStatus.length; i++)
                    {
                        if (self.criteriaListStatus[i].selected == false)
                        {
                            self.userManipulated = false;
                            self.HideResetLink(); 
                            break;                                             
                        }    
                    }            
                }    
                break;        
            }      
        }          
        
        //debug("id er "+self.criteriaListStatus[0].id);
        fc.CriteriaChange_ControlMultiLevelCheckbox(self.name, self.criteriaListStatus, true); 
        DebugRemoveTab()
        debug("~MultiLevelCheckbox["+self.name+"].CheckboxClicked()");   
    }   
    
    function ReplaceAll(Source,stringToFind,stringToReplace){

      var temp = Source;

        var index = temp.indexOf(stringToFind);

            while(index != -1){

                temp = temp.replace(stringToFind,stringToReplace);

                index = temp.indexOf(stringToFind);

            }

            return temp;

    }  
    
    this.ShouldCheckboxBeChecked = function(facetPath, list)
    {
        var temp1;
        var temp2;
        for (var i=0; i<list.length; i++)
        {
            temp1 = list[i].replace(/\//gi, "");
            temp1 = temp1.replace("*", "");
    
            temp2 = facetPath.replace(/\//gi, ""); 
            temp2 = temp2.replace("*", "");
            
            if (temp1 == temp2)
            {
                return true;
            }
        }    
        return false;
    }  
    
    this.OnSearchResult = function(data, _this, persistedSearch)
    {      
        debug("ControlMultiLevelCheckbox["+self.name+"].OnSearchResult()"); 
		
		if (window.console)
			console.log('OnSearchResult(' +self.name + ')');

        DebugAddTab();
              
        $jq("div#"+self.contentDivId).html("");
        
        var temp;
        var facetFieldObj=null;   
        var facetFieldText; 
        var facetFieldId;
        var facetFieldCount;  
        var evalExpression = "facetFieldObj = "+self.facetFieldObjPath;
        self.checkboxPathArray = new Array();
                        
        // ------------------------------------------------------------------------------
        //  Create list of used (in query as parameter) facet field Id's. This is used 
        //  to determine if a checkbox should be checked or not.
        // ------------------------------------------------------------------------------
        var fq = ""//data.responseHeader.params.fq; 
       // debug("fq="+fq);            
       // debug("Add used facet field ids to list:");
       // debug("[");

            
        var listUsedFacetFieldIds = new Array();
        var temp = fq.split(self.facetFilter+":");
        //alert("fq was split into "+temp.length+" parts by '"+self.facetFilter+":");
        var temp2;
        for(var i=1; i<temp.length; i++)
        {            
            temp2 = temp[i].split(")")[0];    
            if (temp2 != "*")
            {
                listUsedFacetFieldIds.push(temp2);			
                debug("  "+temp2);              
            }
        }
        debug("]");
 
        debug("facet field objects:");   

        // ------------------------------------------------------------------------------
        //  Go through each facetField (example: "¤category1|18¤category2|41")and break 
        //  each one into seperate categories. A category has an Id and a Text part. 
        //  Each category in a facetField is to be shown with a margin or indent which
        //  corresponds to its position in the facetyField.
        //  Example:
        //  [x] category1
        //      [x] category2    
        //
        //  If next facetField's first category is "category1" then the subsequent category
        //  must be placed under category1 just below category2 like this:
        //
        //  [x] category1
        //      [x] category2 
        //      [x] subsequent category
        //
        //  and NOT like this:
        //
        //  [x] category1
        //      [x] category2 
        //  [x] category1       // dont show this as it has already been displayed.
        //      [x] subsequent category        
        //
        //  It is assumed that facetField object (array) in result is sorted so that 
        //  (in example below) category1 would never come after category2. 
        //      "¤category1|18¤category2|41"
        //      "¤category1|18¤category5|41" 
        //      "¤category2|7¤category6|41"
        //
        //       
        // ------------------------------------------------------------------------------
        var facetField;     // Example: "/category1|18/category2|41"
        var categories;     //array of categories of this form: "category1|18"
        var categoryText;   //text part of a category: "category1" 
        var categoryId;     //text part of a category: "18"  
        var temp;    
        var html="";        // divs, input etc which is to be attached to content div.
        var prevCategories = new Array();
        var InputIds = new Array();     // checkbox input id's are stored here temporarily. Used to bind events to which cannot be done 
                                        // before html has been written to page.
        self.criteriaListStatus = new Array();  
             
        eval(evalExpression);            
        for(var i=0; i<facetFieldObj.length/2; i++)
        {
            if (facetFieldObj[i*2] != null)
            {
                // ---------------------------------------------
                //  Break down facetField into categories.
                // ---------------------------------------------
                facetField = facetFieldObj[i*2];     
                facetFieldCount = facetFieldObj[i*2+1]; 
                debug("  facetText: "+facetField);
                
                
                // facetField example:                     "¤category1|18¤category2|41"
                categories = facetField.substring(1);   // "category1|18¤category2|41"   
                categories = categories.split("¤");                   
                
                /*
                if (facetField.substring(1, 10) == "Category1") 
                {
                    alert("  facetText: '"+facetField+"' deles til "+categories.length);
                    for(var k=0; k<categories.length; k++)
                    {
                        alert(" split["+k+"] == "+categories[k]);
                    }
                    
                } */
  
                // ---------------------------------------------
                //  Show array of categories as html.
                // ---------------------------------------------                             
                for(var j=0; j<categories.length; j++)
                {
                    temp = categories[j].split("|");
                    categoryText = temp[0];    
                    //debug("    "+categoryText+"(id="+categoryId+")");
                    categoryId   = temp[1];  

                    if (prevCategories[j] == categoryId) 
                    {
                        // don't show this as it has already been displayed previously.
                        continue; 
                    }   

                    if (prevCategories.length <= j)
                    {
                        prevCategories.push(categoryId);  
                        //if (i<5) 
                          //  alert(" prevCategories["+j+"]="+categoryId); 
                    } 
                    else
                    {
                        prevCategories[j] = categoryId;  
                        //if (i<5)
                          //  alert(" prevCategories["+j+"]="+categoryId);   
                    }
                    
                    var facetPath = self.test(prevCategories, j+1);
                    var checked = self.ShouldCheckboxBeChecked(facetPath, listUsedFacetFieldIds);    
                    var margin=j*14;
                    var id = "MultiLevelCheckbox_"+self.name+"_"+categoryId;
                    html += "<div style='float: left' id='MultiLevelCheckbox_"+self.name+"_"+categoryId+"'  >";
                        
                        if (checked)
                        {
                            self.ShowResetLink();
                            html += "<input path='"+facetPath+"' style='margin-left:"+margin+"px;' class='MultiLevelCheckboxInput' id='MultiLevelCheckbox_"+self.name+"_"+categoryId+"' type='checkbox' checked />";
                        }
                        else
                        {
                            html += "<input path='"+facetPath+"' style='margin-left:"+margin+"px;' class='MultiLevelCheckboxInput' id='MultiLevelCheckbox_"+self.name+"_"+categoryId+"' type='checkbox' />"; 
                        }
                        self.checkboxPathArray[id] = facetPath;
                        html += "<div class='MultiLevelCheckboxText'>"+categoryText+"</div>";
                        html += "<div id='MultiLevelCheckbox_"+self.name+"_"+categoryId+"_Num' class='MultiLevelCheckboxText' style='float:left;'>";
                            if (j==categories.length-1) // only last has count
                            {
                                html += "&nbsp;("+facetFieldCount+self.textAfterCount+")";
                            }
                            InputIds.push("MultiLevelCheckbox_"+self.name+"_"+categoryId);
                        html += "</div>";
                            
                    html += "</div>";
                    html += "<div style='clear: both'></div>";   
                    
                    criteria = new ControlMultiCheckboxCriteria("MultiLevelCheckbox_"+self.name+"_"+categoryId, categoryText, categoryId, checked);
                    criteria.facetFieldObjPath = self.facetFieldObjPath;
                    criteria.facetFilter = self.facetFilter;                          
                    criteria.facetPath = facetPath;
		    criteria.logicOperator = self.logicOperator;
                    self.criteriaListStatus.push(criteria);                 
                }               
            }
        } 
        
        if (persistedSearch)
        {
            fc.CriteriaChange_ControlMultiLevelCheckbox(self.name, self.criteriaListStatus, false);   
        }
        
        $jq("div#"+self.contentDivId).html(html); 
        
        for(var i=0; i<InputIds.length; i++)
        {
            //alert("bind to: "+"input#"+InputIds[i]);
            $jq("#"+InputIds[i]).bind('click', {cbId: InputIds[i]}, self.CheckboxClicked);
        }
        

        DebugRemoveTab();
        debug("~ControlMultiLevelCheckbox["+self.name+"].OnSearchResult()");         
    }    
    
    this.test = function(categoryPathElements, count)
    {
        
        var path = "";
        for(var i=0; i<count; i++)
        {
            //if (i>0)
           // {
                path += "/";
           // } 
            path += categoryPathElements[i]; 
            
           // alert("i="+i+" path so far: "+path);
        }
        return path;
    }

}