/**
 * 
 */

escape = encodeURI;

var evapi = { };

evapi.apifacet = function(name, key, withCurrency) {

  return {
    "name": name,
    "key": key,
    "withCurrency": withCurrency
  };
};

evapi.facet = { };

evapi.facet.NONE = evapi.apifacet("", "");

evapi.facet.BUSINESSAREA = evapi.apifacet("facet.businessarea", "bsnssr");
evapi.facet.RESORT = evapi.apifacet("facet.resort", "rsrt");

evapi.facet.TYPE = evapi.apifacet("facet.type", "typ");
evapi.facet.YACHTTYPE = evapi.apifacet("facet.yachtType", "yachtyp");
evapi.facet.OBJECTTYPE = evapi.apifacet("facet.objecttype", "objcttyp");

evapi.facet.GEOGRAPHY = evapi.apifacet("facet.geography");
evapi.facet.COUNTRY = evapi.apifacet("facet.country", "cntry");
evapi.facet.REGION =  evapi.apifacet("facet.region", "rgn");
evapi.facet.DISTRICT = evapi.apifacet("facet.district", "dstrct");
evapi.facet.LICENCEAREA = evapi.apifacet("facet.licenceArea", "lcncr");
evapi.facet.LIVINGSPACE = evapi.apifacet("facet.livingspace", "lvngspc");

evapi.facet.ROOMS = evapi.apifacet("facet.rooms", "rms");
evapi.facet.BEDROOMS = evapi.apifacet("facet.bedrooms", "bdrms");
evapi.facet.PRICE = evapi.apifacet("facet.price", "prc", true);
evapi.facet.RENT = evapi.apifacet("facet.rent", "rnt", true);
evapi.facet.WEEKLYRENT = evapi.apifacet("facet.weeklyRent", "w_rnt", true);

evapi.facet.YACHTLENGTH = evapi.apifacet("facet.yachtLength", "ylen");

evapi.facet.DIVIDABLEFROM = evapi.apifacet("facet.dividableFrom", "dvdblFrm");
evapi.facet.TOTALSURFACE = evapi.apifacet("facet.totalsurface", "ttlsrfc");
evapi.facet.AREA = function( unit ) {
  return evapi.apifacet("facet.area", "area_" + unit);
};

evapi._config = {

  "selectDefaultValue": "?",
  "servlet_context": "",
  "inline_api_handler": "/inline/api"
};

evapi.configure = function(settings) {

  $.extend(evapi._config, settings);
};

evapi._get = function(context, url, parameters, responseHandler) {
  $.extend(parameters, context);
  var target = evapi._config["servlet_context"] + evapi._config["inline_api_handler"] + url;
  $.getJSON( target, parameters, responseHandler);
}

evapi._search = function(context, parameters, responseHandler) {
  
  evapi._get(context, "/search", parameters, responseHandler);
}

evapi.context = function(language, units, currency) {

  return {
    "language": language,
    "localization_country": units,
    "localization_currency": currency
  };
};

evapi.defineContext = function(language, units, currency) {

  evapi._context = evapi.context(language, units, currency);
};

evapi.query = function(context, query, responseHandler) {

  return evapi._search(context, { "q": query }, responseHandler);
};

evapi.filter = function(context, facets, responseHandler) {
  
  return evapi._search(context, { "facets": facets.toString() }, responseHandler);
};

evapi.facets = function() {

  var accumulator = { };
  
  accumulator._facets = [ ];
  
  accumulator.add = function(apifacet, value) {
  
   var key = apifacet.key;
   
   if (apifacet.withCurrency) {
   
     key = key + "_" + evapi._context.localization_currency;
   }
   
   accumulator._facets.push({
     "key": key,
     "value": value
   });
 
    return accumulator;
  };
  
  accumulator.toString = function() {
    
    return $.map($.grep(accumulator._facets, function(facet) {
         return facet.value != null && facet.value.length > 0;
      }), function(facet) {
      
      return facet.key + ":" + facet.value;
    }).join(";");
  };
  
  return accumulator;
}



evdom = { };

evdom.registeredFacetAdapters = { };

evdom.queueEvent = function(fnEvent) {

  if (!evdom.events) {
  
    evdom.events = [];
  }
  
  //evdom.events.push(fnEvent);
  fnEvent();
};

evdom.executeEventQueue = function() {
  
  if (!evdom.events) {
  
    return;
  }
  
  window.setTimeout(function() {
    
    for (var i = 0; i < evdom.events.length; ++i) {
  
      evdom.events[i]();
    }
    
    evdom.events = [];
  }, 0);
  
};

evdom.registerFacetAdapter = function(apiFacet, facetAdapter, useInFilter, hideFromQuery) {

  facetAdapter.apiFacet = apiFacet;
  
  if (facetAdapter.registerChangeListener) {
  
    facetAdapter.registerChangeListener();
  }
  
  facetAdapter.useInFilter = useInFilter;
  facetAdapter.hideFromQuery = hideFromQuery;
  
  evdom.registeredFacetAdapters[facetAdapter.apiFacet.name] = facetAdapter;
  
};

evdom.updateFacet = function(facetModel, updatedAccumulator) {

  var adapter = evdom.registeredFacetAdapters[facetModel.name];
  
  updatedAccumulator[facetModel.name] = 1;
  
  if (facetModel.children) {
    var i;
    for (i = 0; i < facetModel.children.length; ++i) {
    
      var childFacetModel = facetModel.children[i];
      evdom.updateFacet(childFacetModel, updatedAccumulator);      
    }
  }
  
  if (facetModel.values) {
    if (facetModel.values.length == 1 && facetModel.values[0].selected && !facetModel.values[0].autoSelected) {
    
      var adapter = evdom.registeredFacetAdapters[facetModel.name];
      if (adapter && adapter.setState) {
      
        adapter.setState(facetModel.values[0].value);
      }
      return;
    }
  }
  
  if (adapter && adapter.updateValues) {
    
    var state;
    if (adapter.getState) {
      state = adapter.getState();
    }
    
    adapter.updateValues(facetModel.values, state);
    return true;
    
  } else {
    
    return false;
  }
};

evdom.updateFacets = function(json) {

  var i;
  var updated = { };
  for (i = 0; i < json.facets.length; ++i) {
  
    var facetModel = json.facets[i];
    evdom.updateFacet(facetModel, updated);
  }
  
  for (i in evdom.registeredFacetAdapters) {
    
    var facetAdapter = evdom.registeredFacetAdapters[i];
    if (!updated[facetAdapter.apiFacet.name]) {
      if (facetAdapter.updateValues) {
        facetAdapter.updateValues();
      }
    }
  }
  
};

evdom.createConstantAdapter = function(value) {

  return {
    "getValue": function() {
    
      return value;
    }
  };
};

evdom.createRadioChangeListener = function(jradio, radioValue, excludeFacets) {
  
  return function() {
    
    jradio.click(function() {
    
      if (radioValue.onChange) {
      
        radioValue.onChange();
      }
      
      evdom.refresh(excludeFacets);
    });
  };
};

evdom.createRadioAdapter = function(radioName, radioValues, excludeFacets) {

  var parentForm;
  
  var adapter = { };

  var getValues = [ ];
  
  var registerChangeListeners = [ ];
  
  var jradios = [ ];
  
  var radios = [ ];
  
  var excludeLookup = evdom.createExcludeLookup( [] );
  
  var i;
  for (i in radioValues) {
  
    var radioValue = radioValues[i];
    var id = "input#" + radioName + "_" + radioValue.value;
    
    var jradio = $(id);
    var radio = jradio[0];
    
    jradios.push(jradio);
    radios.push(radio);
    
    if (parentForm == null) {
      parentForm = radio.form;
    }
    
    registerChangeListeners.push(evdom.createRadioChangeListener(jradio, radioValue, excludeLookup));
  }


  adapter.getValue = function() {
  
    var i;
    for (i = 0; i < radios.length; ++i) {
    
      var radio = radios[i];
      if (radio.checked) {
      
        if (radioValues[i].facetValue != null) {
        
          return radioValues[i].facetValue;
        }
        else {
        
          return radio.value;
        }
      }
    };
  };
  
  adapter.registerChangeListener = function() {
    
    var i;
    for (i = 0; i < registerChangeListeners.length; ++i) {
      
      var registerChangeListener = registerChangeListeners[i];
      registerChangeListener();
    }
  };
  
  return adapter;
  
};

evdom.createExcludeLookup = function(excludeFacets) {


  var exclude = { };
  
  if (excludeFacets) {
    var i;
    for (i = 0; i < excludeFacets.length; ++i) {
  
      var excludeFacet = excludeFacets[i];
      exclude[excludeFacet.name] = 1;
    }
  }
  
  return exclude;
};

evdom.getSelectbox = function(selectboxId, excludeFacets) {
 
  var jselect = $("select#" + selectboxId);
  
  return {
    "jselect": jselect,
    "select": jselect[0],
    "exclude": evdom.createExcludeLookup(excludeFacets)
  };
}

evdom.selectboxSelection = function(select) {

   var index;
   var selection = new Array();

   var i;
   for ( i = 0; i < select.options.length; ++i ) {

     if ( select.options[i].selected ) {
       selection[selection.length] = select.options[i].value;
     }
   }

   return selection;
}

evdom.createSelectboxAdapter = function(defaultValue, selectboxId, triggersUpdate, excludeFacets, hideCount) {
  
  var adapter = {
    
    "getValue": function() {
      
      var selectbox = evdom.getSelectbox(selectboxId, excludeFacets);
      var jselect = selectbox.jselect;
      var select = selectbox.select;
      
      return evdom.selectboxSelection( select );
    },
    "getState": function() {
    
      var selectbox = evdom.getSelectbox(selectboxId, excludeFacets);
      var jselect = selectbox.jselect;
      var select = selectbox.select;
      
      return evdom.selectboxSelection( select );
    },
    "setState": function(state) {
     
      if ( state.constructor != Array ) {
        state = [ state ];
      }
      
      var selectbox = evdom.getSelectbox(selectboxId, excludeFacets);
      var jselect = selectbox.jselect;
      var select = selectbox.select;
      
      var i;
      var k;
      for (i = 0; i < select.options.length; ++i) {
        for (k = 0; k < state.length; ++k) {
        
          if ( state[k] == select.options[i].value ) {
            select.options[i].selected = true;
          }
          
        }
      }
      
    },
    "updateValues": function(values, state) {
      
      if ( !state ) {
        state = [ ];
      }
      
      if ( state.constructor != Array ) {
        state = [ state ];
      }
      
      var selectbox = evdom.getSelectbox(selectboxId, excludeFacets);
      var jselect = selectbox.jselect;
      var select = selectbox.select;
      var exclude = selectbox.exclude;
      
      var newselect = select.cloneNode(false);
      
      jselect.before(newselect).remove();
      select = newselect;
      jselect = $("#" + selectboxId);
      
      if (triggersUpdate) {
  
        jselect.change(function(handler) {
      
          evdom.refresh(exclude);
        });
      }
      
      if (values == null) {
        values = [];
      }
      
      if ( values.length == 0 ) {
        jselect.attr("disabled",  "disabled");
      } else {
        jselect.removeAttr("disabled");
      }

      var offset = 0;
      var recoverSelectedIndex = new Array();
      var selectedIndex = new Array();
      
      if (values.length != 1 || !values[0].autoSelected) {
        $._option_({ "value": "" }).text(defaultValue ? defaultValue : evapi._config.selectDefaultValue).appendTo(jselect);
        offset = 1;
      }
      
      var i;
      var k;
      for (i = 0; i < values.length; ++i) {
      
        var value = values[i];
        var displayValue = value.displayValue;
        
        if (triggersUpdate && !hideCount) {
          displayValue += " (" + value.count + ")"
        }
        
        $._option_({ "value": value.value }).text(displayValue).appendTo(jselect);
        
        if (value.selected || value.autoSelected) {
          selectedIndex[selectedIndex.length] = i + offset;
        }
        for ( k = 0; k < state.length; ++k ) {
          if ( value == state[k] ) {
            recoverSelectedIndex[recoverSelectedIndex.length] = i + offset;
          }
        }
      }
      
      if (recoverSelectedIndex.length > 0) {
        selectedIndex = recoverSelectedIndex;
      }
      
      for ( i = 0; i < selectedIndex.length; ++i ) {
        select.options[selectedIndex[i]].selected = true;
      }
      
      if ( selectedIndex.length == 0 && select.options.length > 0 ) {
        select.options[0].selected = true;
      }
      
    }
  };
  
  if (triggersUpdate) {
    adapter.registerChangeListener = function() {
      
      var selectbox = evdom.getSelectbox(selectboxId, excludeFacets);
      var jselect = selectbox.jselect;
      var exclude = selectbox.exclude;
      
      jselect.change(function() {
      
        evdom.refresh(exclude)
      });
    };
  }
  
  return adapter;
};

evdom.getApiFacets = function(forQuery, excludeFacets) {

  if (excludeFacets == null) {
    
    excludeFacets = { };
  }
  
  var apiFacets = evapi.facets();
  
  var i;
  for (i in evdom.registeredFacetAdapters) {
  
    var adapter = evdom.registeredFacetAdapters[i];
    if ((forQuery && !adapter.hideFromQuery) || (!forQuery && adapter.useInFilter && !excludeFacets[adapter.apiFacet.name])) {
      if (adapter.getValue) {
        var value = adapter.getValue();
        if ( value.constructor == Array ) {
          var k;
          for (k in value) {
            apiFacets.add(adapter.apiFacet, value[k]);
          }
        }
        else {
          apiFacets.add(adapter.apiFacet, value);
        }
      }
    }
  }
  
  return apiFacets;
};

evdom.refresh = function(excludeFacets, responseHandler) {

  $("*").addClass("busy");
  
  if (responseHandler == null) {
  
    responseHandler = evdom.updateForm;
  }
  
  evapi.filter(evapi._context, evdom.getApiFacets(false, excludeFacets), responseHandler);
};

evdom.load = function(selections, responseHandler, results) {

  if (results == null) {
  
    results = [ ];
    
    evdom.refresh( { }, evdom.createLoadResponseHandler(selections, results));
    return;
  }
  
  if (selections.length == 0) {
    var i;
    for (i = 0; i < results.length; ++i) {
    
      evdom.updateFacets(results[i]);
    }
  }
  else {
  
    
     var selection = selections.shift();
     var adapter = evdom.registeredFacetAdapters[selection.facet.name];
     if (adapter.setState) {
       adapter.setState(selection.value);
     }
  }
  
};

evdom.createLoadResponseHandler = function(selections, results) {

  return function(json) {
  
      results.push(json);
      
      evdom.load(selections, evdom.createLoadResponseHandler(results), results);
      
    };
};

evdom.registerForm = function(jform) {

  var form = jform[0];
  
  jform.submit(function() {
  
      var apiFacets = evdom.getApiFacets(true);
      var searchURL = form.action + "facets=" + escape(apiFacets.toString());
      
      var resultsWindow = window.open(searchURL);
      resultsWindow.focus();
      
      return false;
  });

};

evdom.createRedirect = function(url) {

  return function() {
  
    document.location.href = url;
  }
};

evdom.updateForm = function(results) {

  results = results.results;
  
  for (var i = 0; i < results.length; ++i) {
    
    evdom.updateFacets(results[i]); 
  }
  
  $("*").removeClass("busy");
}

evdom.init = function(initialFacets, selections) {

  $("*").addClass("busy");
  
  var facets = initialFacets;
  
  for (i = 0; i < selections.length; ++i) {
    
    facets.add(selections[i].facet, selections[i].value);
  }
  
  evapi.filter(evapi._context, facets, evdom.updateForm);
  
}



