﻿(function($){
  function isoWeekNumber(da)
  {
    function dw(da) {
      var r = da.getDay()-1;
      return r < 0 ? 7 : r;
    }

    var 
    y = parseInt(da.getFullYear()),
    m = parseInt(da.getMonth()),
    d = parseInt(da.getDate()),
    dow = dw(da),
    dow0101 = dw(new Date(y, 0, 1));

    if( m == 0  &&  3 < dow0101 < 7 - (d-1) ){
      dow     = dow0101 - 1;
      dow0101 = dw(new Date(y-1, 0, 1));
      m       = 11;
      d       = 31;
    }
    else if ( m == 11  &&  30 - (d-1) < dw(new Date(y+1, 0, 1)) && dw(new Date(y+1, 0, 1)) < 4 )
    {
      return 1;
    }
    return parseInt(( dw(new Date(y, 0, 1)) < 4 ) + 4 * m + ( 2 * m + (d-1) + dow0101 - dow + 6 ) * 36 / 256);
  }

  jQuery(document).ajaxError(function(event, request, settings){ 

  });
  
  function getCookieParameters() {
    var cookies = {};
    $.each(document.cookie ? document.cookie.split(";") : [], function(){
      var index = this.indexOf("=");
      if(index>=0){
        var params = {};
        $.each(this.substring(index+1).split("&"),function(){
          var index = this.indexOf("=");
          if(index>=0){
            params[$.trim(this.substring(0,index)).toLowerCase()]=this.substring(index+1).replace(/%([0-9a-f]{2})/gi,function(a,b){return String.fromCharCode(parseInt(b,16));});
          }
        });
        cookies[$.trim(this.substring(0,index)).toLowerCase()]=params;
      }
    });
    
    return cookies.latestsearch ? cookies.latestsearch : {};
  }
  
  function parseDate(v){
    var tests = [
      (/^(\d{2})(\d{2})((?:\d{2}){0,2})$/),
      (/^(\d{1,2})\/(\d{1,2})(?:\/((?:\d{2}){1,2}))?$/),
      (/^(\d{1,2})-(\d{1,2})(?:-((?:\d{2}){1,2}))?$/),
      (/^(\d{1,2})\/(\d{1,2})-((?:\d{2}){1,2})$/)];
                          
    var date = null;
    $.each(tests, function(index, item){
      var match = item.exec(v);
      if(match) {
        var d = Number(match[1]);
        var m = Number(match[2])-1;
        var y = match[3].length == 4 ? Number(match[3]) : (match[3].length == 2 ? Number(Date.fullYearStart + match[3]) : (new Date()).getFullYear()); 
        td = new Date();
        td.setFullYear(y,m,d);
        if(d == td.getDate() && m == td.getMonth() && y == td.getFullYear()) {
          date = td;
        }
      }
    });
    return date;
  }

  // Appends a list of sections
  function appendSections(sections, $container, parameters) {
    $.each(sections, function(){
      var $fieldset = $("<fieldset/>").append($("<legend><span>" + this.legend + "</span></legend>"));
      if($.isArray(this.fields)) {
        $.each(this.fields, function(){
          if(this.hidden) {
            var $hidden = $("<input type='hidden' name='" + this.name + "' id='field" + this.name+ "'" + (parameters[this.name] ? " value='" + parameters[this.name] + "'" : "") + "/>");
            $fieldset.append($("<div/>").append($hidden));
          } else if(this.datepicker) {
            var value = parameters[this.name];
            var valueMin = this.datepicker.min ? parameters[this.datepicker.min] : null;
            var valueMax = this.datepicker.max ? parameters[this.datepicker.max] : null;
            if(value) {
              var dateValue = parseDate(value);
              if(dateValue) {
                if(valueMin) {
                  var dateMin = parseDate(valueMin);
                  if(dateValue<dateMin) {
                    value = dateMin.asString("dd-mm-yyyy");
                  }
                }
                if(valueMax) {
                  var dateMax = parseDate(valueMax);
                  if(dateValue>dateMax) {
                    value = dateMax.asString("dd-mm-yyyy");
                  }
                } 
              } else {
                value = "";
              }
            }
            
            var $dp = $("<input type='input' name='" + this.name + "' id='field" + this.name+ "'" + (value ? " value='" + value + "'" : "") + "/>");
            
            $dp.data("required",this.required);
            $dp.data("label",this.datepicker.label);
            $dp.data("invaliddate",this.datepicker.invaliddate);
            
            $dp.change(function(){
              var dateValue = parseDate($dp.val());
              if(dateValue) {
                $dp.val(dateValue.asString("dd-mm-yyyy"))
              }
            }).blur(function(){
              if($dp.val()=="") {
                $dp.val($dp.data("label"));
              }
            }).focus(function(){
              if($dp.val()==$dp.data("label")) {
                $dp.val("");
              }
            }).blur();

            $fieldset.append($("<div/>").append($dp));
            $dp
              .datePicker({ 'horizontalOffset': -167, 'verticalOffset': 21 })
              .bind("dpDisplayed", function(e, div) {
                $(div)
                  .children(":not(iframe):lt(3)").wrapAll("<div class='dp-top'></div>").end()
                  .find(".dp-top").wrap("<div class='dp-topouter'></div>").end()
                  .find(".dp-calendar").wrap("<div class='dp-calendarouter'></div>").end()
                  .append("<div class='dp-bottom'></div>");
                $(".jCalendar").attr({ "cellspacing": 0, "cellpadding": 0 });
              })
              .bind("dpMonthChanged", function() {
                $(".jCalendar").attr({ "cellspacing": 0, "cellpadding": 0 });
              });
            if(valueMin) $dp.dpSetStartDate(valueMin);
            if(valueMax) $dp.dpSetEndDate(valueMax);
          }
        });
      }
      if(this.checkboxes) {
        $.each(this.checkboxes, function(){
          $fieldset.append(
            $("<div><input type='checkbox' name='" + this.name + "' id='field" + this.name+ "'" + (parameters[this.name]=="true" ? " checked='checked'" : "") + "/><label for='field" + this.name + "'>" + this.label + "</label></div>")
          );
        });
      }
      if(this.dropdowns) {
        $.each(this.dropdowns, function(){
          var $dropdown = $("<select name='" + this.name + "' id='field" + this.name + "'/>");
          $dropdown.data("required", this.required);
          var name = this.name;
          function appendOptions(o, $dropdown) {
            $.each(o, function(){
              var $option = $("<option value='" + this.value + "'" + ((parameters[name]!="-1" && parameters[name]==this.value) ? " selected='selected'" : "") + ">" + this.text + "</option>");
              if(this.url) $option.data("url", this.url);
              $dropdown.append($option);
            });
          }
          if($.isArray(this.options)) {
            appendOptions(this.options, $dropdown);
          }
          if($.isFunction(this.options)) {
            this.options(parameters, function(a){
              appendOptions(a, $dropdown);
            });
          }
          $fieldset.append($("<div/>").append($dropdown));
        });
      }
      $container.append($("<div class='section'/>").append($fieldset));
    });
  }
  
  function setCookieParameters($searchform, params) {
    var parameters = {};
    var geolink = [];
    $searchform.find("fieldset.geo input[type=hidden], fieldset.geo select").each(function(){
      var val = $(this).val();
      if(val!="") {
        geolink.push(val);
      }
    });
    parameters["geolink"]=geolink.join(",");
    parameters["geoid"]=geolink[geolink.length-1];
    $searchform.find("input[type=checkbox]").each(function(){
      var $this = $(this); var name = $this.attr("name"); if(name) parameters[name] = $this.is(":checked");
    });
    $searchform.find("select, input[type=hidden], input[type=text]").each(function(){
      var $this = $(this); var name = $this.attr("name"); if(name) parameters[name] = $this.val();
    });
    parameters.search1extended = $searchform.find("#extended").is(":visible");
    var date = new Date(); date.setTime(date.getTime()+(356*24*60*60*1000));
    document.cookie = "latestsearch="+$.param($.extend(params, parameters))+"; expires="+date.toGMTString()+"; path=/";
  };

  $.fn.felinesearch = function(settings) {    
    var cookieParameters = getCookieParameters();

    this.each(function(){
      var $this = $(this);
      var tmp = $this.attr("search");
      var searchParameters = {};
      if(tmp && tmp.length>1)
        $.each(tmp.substring(1).split("&"), function(n,i) {
          var kv = i.split("=");
          if(kv.length=2) searchParameters[kv[0].toLowerCase()]=kv[1];
        });

      var parameters = $.extend({}, cookieParameters, searchParameters);
    
      var $searchform = $("<form action='' method='get'/>").replaceAll($this.closest("div.search"));

      var $container = $("<div class='middle'/>");
      
      function savesearch() {setCookieParameters($searchform, cookieParameters);}
      
      $("<h1>" + ($.isFunction(settings.heading) ? settings.heading(parameters) : settings.heading) + "</h1>").appendTo($container);
      
      var geolink = {};
      if(parameters.geolink) {
        $.each(parameters.geolink.split(","), function(){
          geolink[this]=true;
        });
      }
    
      var $geo = $("<fieldset class='geo'/>").append($("<legend><span>" + settings.geo.legend + "</span></legend>"));
            
      function isSelected(node) {
        var ret = false;
        if($.isArray(node.ids)) {
          $.each(node.ids,function(){
            if(geolink[this]) {
              ret = true;
            }            
          });
        } else {
          if(geolink[node.id]) {
            ret = true;
          }
        }
        return ret;
      }
      
      function createSelect($div, nodes, label) {
        var $select = $("<select/>");
        $("<option value=''>" + label + "</option>").appendTo($select);
        $.each(sortNodes(nodes), function() {
          $("<option value='" + this.id + "'" + (isSelected(this) ? " selected='selected'" : "") + ">" + this.name + "</option>").appendTo($select).data("nodes", this.nodes);
        });
        return $select;
      }
      var createSelects = [
        function($div, nodes, index, type) {
          if ($.isArray(nodes) && nodes.length) {
            createSelect($div, nodes, settings.geo.labels[index].label).appendTo($div).change(function(){
              var $this = $(this).nextAll().remove().end();
              var $selected = $this.find(":selected");
              createSelects[type]($this.closest("fieldset"), getAreaNodes($selected.data("nodes")), index+1, type);
            }).trigger("change").data("required", settings.geo.labels[index].required);
          }
        },
        function($div, nodes, index, type) {
          if ($.isArray(nodes) && nodes.length) {
            var $select = createSelect($div, nodes, settings.geo.labels[index].label).appendTo($div)
            if(index>0) {
            var allNodes = [];
              $.each(nodes,function(){
                if($.isArray(this.nodes)) {
                  $.merge(allNodes, this.nodes);
                }
              });
              $select.find("option:eq(0)").data("nodes",getAreaNodes(allNodes));
            }
            $select.change(function(){
              var $this = $(this).nextAll().remove().end();
              var $selected = $this.find(":selected");
              createSelects[type]($this.closest("fieldset"), getAreaNodes($selected.data("nodes")), index+1, type);
            }).trigger("change").data("required", settings.geo.labels[index].required);
          }
        },
        function($div, nodes, index, type) {
          if ($.isArray(nodes) && nodes.length) {
            var $select = createSelect($div, nodes, settings.geo.labels[index].label).appendTo($div);
            $select.find("option:eq(0)").data("nodes", nodes);
            $select.change(function(){
              var $this = $(this).nextAll().remove().end();
              var $selected = $this.find(":selected");
              var nodes = $selected.data("nodes");
              if($selected.val()!="" && getAreaNodes(nodes).length) {
                createSelects[type]($this.closest("fieldset"), getAreaNodes(nodes), index+1, type);
              } else if(index>0) {
                createSelect($div, getLocationNodes(getSubnodes(nodes)), settings.geo.locationlabel)
                  .appendTo($div)
                  .change(function() { })
                  .trigger("change")
                  .bind('focusin', function() {
                    $(this).css("width", "auto");
                  })
                  .bind('focusout', function() {
                    $(this).css("width", "138px");
                  });
              }
            }).trigger("change").data("required", settings.geo.labels[index].required);
          }
        }
      ];

      function getLocationNodes(nodes) {
        var nodes = filterNodes(nodes,2);
        var unique = {};
        $.each(nodes,function(){
          var node = unique[this.name];
          if(!node) {
            node = unique[this.name] = this;
            node.ids = [];
          }
          node.ids.push(this.id);
        });
        var a = [];
        for(var id in unique) {
          a.push(unique[id]);
        }
        return sortNodes(a);
      }

      function getAreaNodes(nodes) {
        return sortNodes(filterNodes(nodes,function(node){return node.type!=2}));
      }
      function sortNodes(nodes) {
        return nodes.sort(function(a,b){
//          if(a.sort<b.sort) {
//            return -1;
//          } else if(a.sort>b.sort) {
//            return 1;
//          } else {
            if($.isFunction(a.name.localeCompare)) {
              return a.name.localeCompare(b.name);
            }
            else if (a.name<b.name) {
              return -1;
            } else if(a.name<b.name) {
              return 1; 
            } else {
              return 0;
            }
//          }
        });
      }

      function filterNodes(nodes, filter) {
        var ret = [];
        if($.isArray(nodes)) {
          if($.isFunction(filter)) {
            $.each(nodes, function(){
              if(filter(this)) {
                ret.push(this);
              }
            });
          } else {
            $.each(nodes, function(){
              if(this.type == filter) {
                ret.push(this);
              }
            });
          }
        }
        return ret;
      }

      function getSubnodes(nodes) {
        var ret = [];
        if($.isArray(nodes)) {
          $.each(nodes, function(){
            ret.push(this)
            $.merge(ret, getSubnodes(this.nodes));
          });
        }
        return ret;
      }
      
      $.getJSON("/geo/katalogdata.asp", { gruppeid:settings.geo.gruppeid,sprogid:settings.geo.sprogid,ferietypeid:settings.geo.ferietypeid}, function(data, status) {
        if(parameters.miniferie=="true" || parameters.lastminute=="true") {
          var mainid = "746F19A0BD72441087FDB8B3F9994444";
          $("<input type='hidden' value='" + mainid + "'/>").appendTo($geo);
          createSelects[settings.geo.type]($geo, filterNodes(data.nodes,function(node){return (node.id==mainid);})[0].nodes, 1, settings.geo.type);
        } else {
          createSelects[settings.geo.type]($geo, data.nodes, 0, settings.geo.type);
        }
      });

      $container.append($("<div class='section'/>").append($geo));
      
      appendSections(settings.sections, $container, parameters);
  
      $("<input type='submit' value='" + settings.search + "' class='search'/>").appendTo($container);
            
      $searchform.bind("submit", function(e){
        savesearch();
        var parameters = {};
        var errors = false;
        var geolink = [];
        $searchform.find("fieldset.geo input[type=hidden], fieldset.geo select").each(function(){
          var val = $(this).val();
          if(val!="") {
            geolink.push(val);
          }
        });
        parameters["geolink"]=geolink.join(",");
        parameters["geoid"]=geolink[geolink.length-1];
        $searchform.find("input[type=checkbox]:visible").each(function(){
          var $this = $(this); var name = $this.attr("name"); if(name) parameters[name] = $this.is(":checked");
        });
        $searchform.find("select:visible, input[type=hidden], input[type=text]:visible").each(function(){
          if(!errors) {
            var $this = $(this); 
            var name = $this.attr("name"); 
            var value = $this.val();
            if((value=="" || value==$this.data("label")) && $this.data("required")) {
              alert($this.data("required"));
              $this.focus();
              errors = true;
            } else if($this.find("option:selected").data("url")) {
              errors = true;
            } else {
              if($this.data("invaliddate") && !parseDate(value)) {
                alert($this.data("invaliddate"));
                $this.focus();
                errors = true;
              } else {
                if(name) parameters[name] = value;
              }
            }
          }
        });
        if(!errors) {
          location.href=settings.action+"?"+$.param(parameters);
        }
        e.preventDefault();
        return false;
      });
            
      var $extended = $("<div id='extended'/>")
        .toggle(parameters.search1extended=="true")
        .appendTo($container);
  
      appendSections(settings.extended.sections, $extended, parameters);
      
      var $toggleextended = $("<a>" + settings.extended.toggle + "</a>")
        .attr("href","#extended")
        .click(function(){
          $($(this).attr('href')).slideToggle("fast",function(){updatetoggleextended();savesearch();});return false;
        })
      
      var updatetoggleextended = function() {
        if($extended.is(":visible"))
          $toggleextended.removeClass("open").addClass("close");
        else
          $toggleextended.removeClass("close").addClass("open");
      };
      
      
      if($.isArray(settings.persondistribution)) {
        $.each(settings.persondistribution, function(i,o) {
          var
          name = o.name,
          $refadults = $container.find("select[name=" + o.refadults + "]"),
          $refchildren = $container.find("select[name=" + o.refchildren + "]"),
          $refsection = $refchildren.closest("div.section"),
          $section = $("<div class='section'/>"),
          $field = $("<input type='hidden' name='" + name + "'/>"),
          $fieldset = $("<fieldset/>")
            .appendTo($section)
            .append($("<legend><span>" + o.legend + "</span></legend>"))
            .append($field);
          $field.val(parameters[name]);         
          
          function updatepersondistribution() {
            var 
            value = $refchildren.val(),
            intVal = parseInt(value),
            children = [];
            
            $.each($field.val().split(","),function(i,s) {
              var age = parseInt(s);
              if(age<=15) {
                children.push(age);
              }
            });
            
            function appendOptions(options, $dropdown, i) {
              $.each(options, function(){
                var $option = $("<option value='" + this.value + "'" + ((children[i]!="-1" && children[i]==this.value) ? " selected='selected'" : "") + ">" + this.text + "</option>");
                $dropdown.append($option);
              });
            }
            
            function updatefield() {
              var persondistribution = [];
              for(var i=0;i<parseInt($refadults.val());i++)
                persondistribution.push("v");
              $fieldset.find("select").each(function(){
                persondistribution.push($(this).val());
              });
              $field.val(persondistribution.join(","));
            }
            
            $section.toggle(intVal>0);
            if(intVal>0) {                            
              var $dropdown = $field;
              for(var i=0;i<intVal;i++) {
                $dropdown = $dropdown.next("select");
                if($dropdown.length==0) {
                  $dropdown = $("<select/>");
                  $dropdown.data("required", o.required);
                  $dropdown.change(updatefield);
                  appendOptions(o.options, $dropdown, i);
                  $fieldset.append($dropdown);
                }
              }
              $dropdown.nextAll("select").remove();
            }
            updatefield();
          }
          $refchildren.bind("change keyup",updatepersondistribution);
          $refadults.bind("change keyup",updatepersondistribution);
          updatepersondistribution();
          
          $refsection.after($section);
        });
      }

      
      // Wrap container with some markup for layout and add to searchform
      $("<div class='search'/>")
        .append($("<div class='top'/>"))
        .append($container)
        .append($("<div class='bottom'/>").append($toggleextended))
        .appendTo($searchform);
           
      updatetoggleextended();    
           
      $searchform.find("input[type=checkbox]").click(savesearch);
      $searchform.find("input[type=text]").change(savesearch);
      $searchform.find("select").change(function(){
        var url = $(this).find(":selected").data("url");
        if(url) { 
          location.href = url;
          return false;
        } else {
          savesearch();
        }
      }).eq(0).focus();
    });
    
    return this;
  }
  
  $.fn.felinesearch.isoWeekNumber = isoWeekNumber;
})(jQuery);