var isHome;
var isNano;
var isAdvanced;
var assetsLoaded = false;

var defaultView = 'simple';

function searcherValid() {
  var valid = HODest.valid() && HODate.valid() && HORooms.valid();
  if (!valid) searcherShowError();
  else $$(".nodis select, .novis select").each(function(i) { i.selectedIndex = 0 });
  return valid;
}

function initSearcher() {
  var viewField = $("view");
  var view = viewField ? viewField.value : 'simple';

  isNano = !!$("searcher_nano");
  isAdvanced = view == 'advanced';

  if (HODate == undefined) return;

  HODef.init();
  HODest.init();
  if (isNano) {
    HODDate.init();
    FormTips.init("sn_step1");
  } else if (isAdvanced) {
    HODate.init(2);
    HODDate.init();
  } else {
    HODate.init(2);
    HODDate.init();
  }

  HORooms.init();
  if ($("searcherForm"))  $("searcherForm").addEvent("submit", searcherValid);
  if ($("search_type_2")) $("search_type_2").addEvent("click", sendAdvanced);
}

function sendAdvanced(ev) {
  ev.stop();
  location.href = ev.target.href + "&" + $("searcherForm").toQueryString();
}

function enableSubmit(valid) {
	if (valid == undefined) 
		valid = HODest.valid() && HODate.valid() && HORooms.valid();
	if ($("searcher_valid")) (valid) ? $("searcher_valid").removeClass('novis'):$("searcher_valid").addClass('novis');
}

function searcherShowError() {
	enableSubmit();
	evalJson("errors = " + $("errorJson").value );
	var summary = [];
	if (!HODest.checkValid()) summary.push(errors['destination']);
	if (!HODate.checkValid()) summary.push(errors['dates']);
	if (!HORooms.checkValid()) summary.push(errors['rooms']);
	FxBox.showContent("<span class='fxb_msg'><ul><li>"+ summary.join("</li><li>") +"</li></ul></p></span>");
} 

var HODef = {
  init: function() {
    var lastSearch = $("lastSearch");
    if (lastSearch) HODef.list = JSON.decode(lastSearch.value);
      if ( $H(HODef.list).getLength() == 0 ) HODef.list = null;
      HODef.set("textDestination");
      HODef.set("Destination", "IdSearcher");
      HODef.setRoomsSelects();
      if (isNano || ($("ajx") && $("ajx").value=='true')) {
        if ($("hid_destination")) {
          // Set destination in destinations
          $("textDestination").value = $("hid_destination").value;
          $("txtDestText").empty();
        }
        else if ($("codeHotel")) {
          // Set hotel name and hide destination in infoHotel
          $("id_hotel_nano").value = $("codeHotel").value;
          $("hid_advanced").value = "true";
          $("txtDestText").empty();
          $("textDestination").addClass("nodis");
          $("fixedDestination").set( ($("fixedDestination").tagName=="INPUT")?"value":"html", $("nameHotel").value)
                  .removeClass("nodis");
          $("Destination").value="0";
        }
      }
  },
	getDayIn: function() {
		if (!HODef.list) return null;
		return new Date( [HODef.list.MonthIn, HODef.list.DayIn, HODef.list.YearIn].join("/") );
	},
	getDayOut: function() {
		if (!HODef.list) return null;
		return new Date( [HODef.list.MonthOut, HODef.list.DayOut, HODef.list.YearOut].join("/") );
	},
	get: function(key) {
		if (!HODef.list) return "";
		return HODef.list[key];
	},
	set: function(field, key) {
          var f = $(field);
          if (f && HODef.list) {
            var value = HODef.list[key || field];
            if (value) f.value = value;
          }
	},
	setRoomsSelects: function() {
		if (!HODef.list) return;
		$H(HODef.list).filter(function(v,k) { return (v!="" && k.test(/^H/)) })
			.each(function(v,k) { $(k).set('value', v); $(k).fireEvent('change'); });
	},
	list: null
}

var HODest = {
	wick: null,
	init: function() {
		HODest.wick = new Wick("textDestination", {
			ajaxUrl: "/Generator/FreeTexts/FreeText_[l]_"+ window.siteLang +"_[lang].json",
			hiddenField: "Destination", iconField: "loadingIcon",
			onMatch: HODest.doMatch, onDematch: HODest.doDematch,
			listFilter: function(i) { return i.P != "0";},
			gaEventCategory: "Buscador",
			gaEventAction: "Free-Text Destinos"
		});

	},
	valid: function() { return $("Destination").value != ""; },
	checkValid: function(nocheck) { return HODest.valid(); },
	request: null,
	doMatch: function(wk) {
		if ($("zone_block")) {
			if (HODest.request!=null) HODest.request.cancel();
			HODest.request = new Request({ method: 'get', url: '/AJAX/Zones.aspx?idSearcher='+ $("Destination").value, onSuccess: HODest.showZones }).send();
		}
		if ($("free_hotel_name") && $("free_hotel_name").wick) $("free_hotel_name").wick.filterList();
		enableSubmit();
	},
	doDematch: function(wk) {
		if ($("zone_block")) HODest.hideZones();
		if ($("free_hotel_name")) $("free_hotel_name").wick.filterList();
		enableSubmit();
	},
	showZones: function(res) { $("zones").set("html", res); $("zone_block").removeClass("nodis"); },
	hideZones: function() {  $("zone_block").addClass("nodis"); $("zones").set("html", ""); }
}

// ************ DATEPICKER FOR HOME AND AJAX SEARCHER
var HODate = {
  init: function(howMany, elementName) {
    $("datePicker").empty();    
    if (!$(HODate.cnf.elementName)) return false;
    var eName = elementName || HODate.cnf.elementName;
    HODate.element = document.getElementById(eName);
    if (HODate.element == null) return false;
    HODate.createMiniPickers();
    dateTemp=null;
    return this;
  },
        createMiniPickers: function() {
          var container = $("datePicker");
          var wrapper = new Element('div', { 'id':'sn_step2', 'class':'sn_block' });

          var divIn  = new Element('div', { 'id':'dateIn', 'class':'sn_block date'});
          var divOut = new Element('div', { 'id':'dateOut', 'class':'sn_block date'});

          var labelIn  = new Element('label', { 'for':'date_in', 'text':HODate.labelTexts['in'] });
          var labelOut = new Element('label', { 'for':'date_out', 'text':HODate.labelTexts['out'] });
          
          var inputIn  = new Element('input', { 'id':'date_in', 'name':'date_in', 'size':'10' });
          var inputOut = new Element('input', { 'id':'date_out', 'name':'date_out', 'size':'10' });

          container.adopt(wrapper);
          wrapper.adopt(divIn, divOut);
          divIn.adopt(labelIn, inputIn);
          divOut.adopt(labelOut, inputOut);

        },
	checkValid: function(nocheck) {
		if (nocheck == undefined) enableSubmit();
		return !isNano? HODate.valid():HODDate.valid();
	},
	valid: function() {
		return HODDate.valid();

		var dates = HODate.dates;
		var valid = (dates.length == 2) && !isNaN(dates[0].getDay()) && !isNaN(dates[1].getDay())
			&& HODate.checkRanges() && HODate.checkBookToday();
		if (HODate.cnf.showOk) $(HODate.cnf.dateOk).innerHTML = (valid) ? HODate.cnf.dateOkText : "";
		return valid;
	},
	setDate: function(date, fields) {
		$(fields[0]).value = HODate.twoDigits(date.getDate());
		$(fields[1]).value = HODate.twoDigits(date.getMonth()+1);
		$(fields[2]).value = date.getFullYear();
	},
	msToDays: function(ms) {
		return Math.round(ms/(24*60*60*1000));
	},
	clear: function() {
		HODate.cnf.inFields.each(function(i) { $(i).value = ""; });
		HODate.cnf.outFields.each(function(i) { $(i).value = ""; });
		$(HODate.cnf.dateFrom).innerHTML = "";
		$(HODate.cnf.dateTo).innerHTML = "";
		$(HODate.cnf.days).innerHTML = "";
	},
	element: null,
	dates: [],
	twoDigits: function(num) {
		return (num < 10)? "0"+num : ""+num;
	},
	checkRanges: function() {
		var d = HODate.dates;
		if (HODate.msToDays(d[1]-d[0]) < parseInt($(HODate.cnf.rangMin).value, 0)) return false;
		if (HODate.msToDays(d[1]-d[0]) > parseInt($(HODate.cnf.rangMax).value, 0)) return false;
		return true;
	},
	checkBookToday: function() {
		var d0 = HODate.dates[0];
		var today = new Date();
		if ($(HODate.cnf.bookToday).value != "true" && d0.getDate() == today.getDate() && 
			d0.getMonth() == today.getMonth() && d0.getFullYear() == today.getFullYear())
			return false;
		return true;
	},
	cnf: {
		elementName: "datePicker",
		info: "datePickerInfo",
		inFields: ["DayIn", "MonthIn", "YearIn"],
		outFields: ["DayOut", "MonthOut", "YearOut"],
		dateFrom: "dateFrom",
		dateTo: "dateTo",
		days: "dateNight",
		dateOk: "dateOk",
		dateOkText: ssp("<img src='{ssp}img/search/correcto.gif' />"),
		showOk: true,
		rangMin: "RangMin",
		rangMax: "RangMax",
		bookToday: "BookToday"
	},
	cal: null,
        labelTexts: {
          'in'  : 'Arrival',
          'out' : 'Departure'
        }
};

// DATEPICKER FOR DESTINATION FORMS
var HODDate = {
  init: function() {
    this.setDefaultDays();
    // Get days names and set Sunday first
    var daysNames = DateFormat.getWeekDayInitials();
    var monthNames = DateFormat.getMonthNames();
    this.cal = new Calendar({ date_in: 'd/m/Y', date_out: 'd/m/Y' },
            { direction: 0.5, offset:1, tweak: {x:-158, y:20}, days: daysNames, months: monthNames });
    this.cal.addEvent("change", HODDate.setHidFields);
  },
    restrictMonth: function(what) {
        var today = new Date();
        if ($("Year"+what).value == today.getFullYear() && $("Month"+what).value <= today.getMonth())
            $("Month"+what).selectedIndex = today.getMonth() + 1;
    },
    setDefaultDays: function(ev) {
		if (HODef.list) {
			var dateIn  = "{d}/{m}/{y}".substitute({ d:HODef.get("DayIn"), m:HODef.get("MonthIn"), y:HODef.get("YearIn") });
			var dateOut = "{d}/{m}/{y}".substitute({ d:HODef.get("DayOut"), m:HODef.get("MonthOut"), y:HODef.get("YearOut") });
			if (dateIn === "//") dateIn = "";
			if (dateOut === "//") dateOut = "";
			$("date_in").set("value", dateIn);
			$("date_out").set("value", dateOut);
			["DayIn","MonthIn","YearIn","DayOut","MonthOut","YearOut"].each(function(i) {
				$(i).value = HODef.get(i);
			})
		} else {
			$("date_in").set("value", "");
			$("date_out").set("value", "");
		}
    },
	checkRanges: function() {
		var d = this.cal.calendars.map(function(i) {return i.val});
		if (HODate.msToDays(d[1]-d[0]) < parseInt($(HODate.cnf.rangMin).value, 0)) return false;
		if (HODate.msToDays(d[1]-d[0]) > parseInt($(HODate.cnf.rangMax).value, 0)) return false;
		return true;
	},
	checkBookToday: function() {
		var d0 = this.cal.calendars[0].val;
		var today = new Date();
		if ($(HODate.cnf.bookToday).value != "true" && d0.getDate() == today.getDate() && 
			d0.getMonth() == today.getMonth() && d0.getFullYear() == today.getFullYear())
			return false;
		return true;
	},
	setHidFields: function() {
		// this is calendar object
		HODDate.setDate(this.calendars[0].val, ["DayIn","MonthIn","YearIn"]);		
		HODDate.setDate(this.calendars[1].val, ["DayOut","MonthOut","YearOut"]);
		HODDate.checkValid();
	},
	setDate: function(date, fields) {
		if (date) {
			$(fields[0]).set("value", TwoDigits(date.getDate()));
			$(fields[1]).set("value", TwoDigits(date.getMonth()+1));
			$(fields[2]).set("value", date.getFullYear());
		} else
			fields.each(function(i) { $(i).set("value",""); });
	},
	valid: function() {
        var valid = this.cal && this.cal.calendars[0].val != null && this.cal.calendars[1].val != null
                && this.checkBookToday() && this.checkRanges();
        if (HODate.cnf.showOk && $(HODate.cnf.dateOk)) $(HODate.cnf.dateOk).innerHTML = (valid) ? HODate.cnf.dateOkText : "";
        return valid;
    },
    checkValid: function() { return HODDate.valid(); }
}

function TwoDigits(value) {
	return (value < 10)? "0"+value:""+value;
}

Date.prototype.getMonthDay= function(){
	var dTempx=new Date(this);
	var dTempa=dTempx.setDate(1);
	var dTempb= dTempx.setMonth(dTempx.getMonth()+1);
	var daysMonth= Math.round((dTempb-dTempa)/(24*60*60*1000));
	dTempx=dTempa=dTempb=null;
	return parseInt(daysMonth);
};
Date.prototype.plusDate= function(){
	var dTemp=this;
	arguments[0]=(arguments[0])?(dTemp.getFullYear()+arguments[0]):dTemp.getFullYear();
	arguments[1]=(arguments[1])?(dTemp.getMonth()+arguments[1]):dTemp.getMonth();
	arguments[2]=(arguments[2])?(dTemp.getDate()+arguments[2]):dTemp.getDate();
	arguments[3]=(arguments[3])?(dTemp.getHours()+arguments[3]):dTemp.getHours();
	var plusD=new Date(arguments[0],arguments[1],arguments[2],arguments[3]);
	return plusD;
};
Date.prototype.compareDate= function(){
	var aTemp= new Date(arguments[0]);
	var bTemp= new Date(arguments[1]);
	return ((this.toString()==arguments[0]) || this>aTemp&&this<bTemp || (this.toString()==arguments[1]));
};
Date.prototype.pickerElement = null;
Date.prototype.calendars=new Array;	
Date.prototype.selDates=new Array;	
Date.prototype.spans=new Array;	
Date.prototype.createCalendar= function(sId, element){
	element = element || this.pickerElement ||document.body;
	this.pickerElement = element;
	var nowOK=new Date();
	nowOK.setHours(0);
	nowOK.setMinutes(0);
	nowOK.setSeconds(0);
	nowOK.setMilliseconds(0);
	this.now=nowOK;
	this.format=new Date(this.getFullYear(),this.getMonth(),this.getDate());
	this.capaCal=document.getElementById(sId);
	this.sid=sId;
	var oFragment = document.createDocumentFragment();
	oFragment.appendChild(this.controlCalendar());
	oFragment.appendChild(this.calendarDays());
	//oFragment.appendChild(this.dayInDayOut());
	if(!this.capaCal){
		this.capaCal = document.createElement('div');
		this.capaCal.className='calendar';
		this.capaCal.setAttribute('id',this.sid);
	}
	else this.capaCal.innerHTML='';
	this.capaCal.appendChild(oFragment);
	this.calendarInit();
	// if (element == undefined) element = document.body;
	this.pickerElement.appendChild(this.capaCal);
	this.pickerElement.calendar = this;
};
Date.prototype.controlCalendar=function(){
	var oTemp=this;
        var m_index = this.getMonth();
	var oFragA= document.createDocumentFragment();
	var capaCtrA = document.createElement('div');
	capaCtrA.className='controller';
	var elemnts=new Array('name');
	var numbCals=oTemp.calendars.length-1;
	if(oTemp.sid=='month0') elemnts.unshift('less');
	else if(oTemp.sid=='month'+numbCals) elemnts.push('plus');
	for(i=0;i<elemnts.length;i++){
		switch (elemnts[i]){
			case 'less':
				var capaA= document.createElement('a');
				capaA.className='month_down';
				capaA.setAttribute('href','#nohref');
				capaA.innerHTML='&nbsp;&nbsp;&nbsp;';
				break;
			case 'name': 
				var capaA= document.createElement('span');
				capaA.className='actual_month';
				capaA.innerHTML=DateFormat.getMonthNames()[m_index] + '&nbsp;'+oTemp.getFullYear();
				break;
			case 'plus': 
				var capaA= document.createElement('a');
				capaA.className='month_up';
				capaA.setAttribute('href','#nohref');
				capaA.innerHTML='&nbsp;&nbsp;&nbsp;';
				break;
			default: return false;
			}
		capaCtrA.appendChild(capaA);
		}
	var capaCtrB = document.createElement('div');
	capaCtrB.className='days_week';
	if(arguments[0]){var x=0; var y=6}
	else {var x=1; var y=7}
	var dayNames = DateFormat.getWeekDays();
        dayNames.push(dayNames.shift());
        for (i = 0; i < dayNames.length; i++) {
          if (dayNames[i]) dayNames[i] = dayNames[i].substring(0,2);
        }

	for(i=x;i<=y;i++){
		var capaB= document.createElement('span'); 
		capaB.className='dp_void';
		// capaB.innerHTML=i+'&nbsp;';
		capaB.innerHTML= (dayNames) ? dayNames[i-1] : i+'&nbsp;';
		capaCtrB.appendChild(capaB);
		}
		capaCtrA.appendChild(capaCtrB);
		oFragA.appendChild(capaCtrA);
	oTemp=null;
	return capaCtrA;
	};
Date.prototype.calendarDays=function(){
	var oTemp= this.format;
	oTemp.setDate(1);
	var wDay=(oTemp.getDay()==0 && !arguments[0])? 7:oTemp.getDay();
	var mDay= oTemp.getMonthDay();
	var capaDays = document.createElement('div');
	capaDays.className='calendar_days';
	var oFrag= document.createDocumentFragment();
	for(i=1;i<(mDay+wDay);i++){
		var dia=(i-wDay);
		if(arguments[0]&&i==1){i--;arguments[0]=null;}
		var capaC= document.createElement('a');
		capaC.href='#void';
		if(i>=wDay){
			var newTemp=oTemp.plusDate(0,0,dia);
			capaC.id=newTemp.toDateString();
			capaC.title=DateFormat.format(newTemp);
			if(this.now>newTemp){ capaC.className='past';}
			else{
				if(newTemp>this.now){ 
					if(newTemp.compareDate(oTemp.selDates[0], oTemp.selDates[1]))capaC.className='active';
					else capaC.className='valid';}
				else capaC.className='today';
				oTemp.spans.push(capaC);}
			capaC.innerHTML=dia+1+'&nbsp;';
			}
		else{capaC.className='dp_void';
			capaC.innerHTML='&nbsp;';
			}
		oFrag.appendChild(capaC);
		}
	capaDays.appendChild(oFrag);
	oNTemp=oTemp=null;
	return capaDays;
	};
Date.prototype.calendarInit=function(oEvent) {
	var oThis = this;
	oThis.capaCal.ondblclick= function () {return false;};
	oThis.capaCal.onclick =  function (oEvent) {
		oEvent = oEvent || window.event;
		oTarget = oEvent.target || oEvent.srcElement;
		switch(oTarget.className){
			case 'month_down':
				var otNew=oThis.plusDate(0,-1);
				if(otNew>=oThis.now.setDate(1)){
					oThis.spans.length=0;
					for(o=0;o<oThis.calendars.length;o++){var lessM=-(oThis.calendars.length-o-1);
						var oNew=oThis.plusDate(0,lessM);
						oNew.createCalendar(oThis.calendars[o],oThis.pickerElement);
						};
					}
				otNew=oNew=null;
				break;
			case 'month_up':
				oThis.spans.length=0;
				for(o=0;o<oThis.calendars.length;o++){
					var oNew=oThis.plusDate(0,o);
					oNew.createCalendar(oNew.calendars[o],oThis.pickerElement);
					};
				oNew=null;
				break;
			case 'controller': return false;
			case 'calendar': return false;
			case 'dp_void': return false;
			case 'past': return false;
			default:
				if (oTarget.id == "") return false;
				oThis.selectDay(oTarget.id);
				break;
			}
		}
	};
Date.prototype.selectDay = function(date) {
	var oThis = this;
	var tempDate=new Date(date);
	if(oThis.selDates.length==2){
		oThis.selDates.length=0;
		oThis.selDates.push(tempDate);//alert(oThis.selDates)
		}
	else if (oThis.selDates[0]<tempDate){oThis.selDates.push(tempDate);}
		else {oThis.selDates.unshift(tempDate);};
	for(o=0;o<oThis.spans.length;o++){
		var TempDate=new Date(oThis.spans[o].id);
		if(TempDate.compareDate(oThis.selDates[0],oThis.selDates[1])){
			oThis.spans[o].className='active';
			}
		else if(TempDate.compareDate(oThis.now)){oThis.spans[o].className='today';}
			else oThis.spans[o].className='valid';
		}
	tempDate=TempDate=null;
};

// ************** ROOMS
var HORooms = {
	init: function() {
	  if (!$("H1")) return false;
		var room = $("pers_room");
		// Hide fields
		room.getElements("label").addClass("nodis"); // novis
		room.getElements("fieldset").addClass("nodis");
		// room.getElements("label, fieldset").each(function(i) { i.addClass("nodis"); });
		// Set ids for fields
		$("number_rooms").getElements("input").each(function(i) { i.id = i.name + "_" + i.value; });
		room.getElements("select").each(function(i) { i.id = i.name; });
		HORooms.setEvents();
		if (!HODef.list) {
			$("H1").set("value", "H1#AD2#CH0");
			HORooms.setRooms(1);
			HORooms.showRows(1);
		} else {
			HORooms.setRooms(HODef.get("RO"));
			HORooms.showRows( parseInt(HODef.get("RO"),0) );
		}
		room.getElements("fieldset.closed").removeClass("closed");
		HORooms.checkValid();
	},
	setEvents: function() {
		for(var i=1; i<=HORooms.cnf.maxRooms; i++)
			$("H"+i).addEvent("change", function() { HORooms.showChildrens(this.value); });
		$$("#pers_room select").each(function(i) {
			i.addEvent("change", function() { setTimeout(HORooms.checkValid, 50);});
		});
		if (this.isSelect())
			$("room_num").addEvent("change", function() {HORooms.showRows(this.value); });
		else
            $("room_num").getElements("input").addEvent("click", function() { HORooms.showRows(this.value); });
	},
	showRows: function(n) {
		for(var i=1; i<=HORooms.cnf.maxRooms; i++)
			(i <= n) ? HORooms.showRow(i) : HORooms.hideRow(i);
		// setTimeout(HORooms.checkValid, 100);
		HORooms.checkValid();
	},
	showRow: function(n) { 
		HORooms.showChildrens( $("H"+n).value );
		$("H"+n).getParent().removeClass("nodis"); // novis
		$("H"+n).getParent(".room").removeClass("nodis");
	},
	hideRow: function(n) {
		$("H"+n).getParent(".room").addClass("nodis");
		$("H"+n).getParent().addClass("nodis"); // novis
	},
	showChildrens: function(value) {
		if (value == "") return false;
		var row = parseInt(value.match(/^H(\d)/)[1], 0);
		var child = parseInt(value.match(/CH(\d)/)[1], 0);
		for(var i=1; i<=HORooms.cnf.maxChild; i++) {
			var label = $("H"+row+"AG"+i).getParent();
			(i <= child) ? label.removeClass("nodis") : label.addClass("nodis"); // Novis
		}
		HORooms.checkValid();
	},	
	getRooms: function() {
		if (this.isSelect())
			return parsetInt( $("room_num").get("value"), 0);
		else
			return parseInt($("searcherForm").getElement("[name=RO]:checked").get("value"), 0);
	},
	setRooms: function(rooms) {
		if (this.isSelect())
			$("room_num").set("value", rooms);
		else {
			$("searcherForm").getElement("[name=RO][value="+rooms+"]").set("checked", "checked");
		}
	},
	checkValid: function(nocheck) {
		if (nocheck == undefined) enableSubmit();
		return HORooms.valid();
	},
	isSelect: function() { return $("room_num").tagName == "SELECT"; },
	valid: function() {
		var list = $A($("pers_room").getElements("select")).filter(function(i) {
			// return (!i.getParent().hasClass("novis") && !i.getParent('fieldset').hasClass("nodis") && i.value == "")
			return (!i.getParent().hasClass("nodis") && !i.getParent('.room').hasClass("nodis") && i.value == "")
		});
		if (HORooms.cnf.showOk && $(HORooms.cnf.okElement)) $(HORooms.cnf.okElement).innerHTML = (list.length == 0)? HORooms.cnf.okText : "";
		return (list.length == 0);
	},
	cnf: {
		maxRooms: 5,
		maxChild: 3,
		okText: ssp("<img src='{ssp}img/search/correcto.gif' />"),
		okElement: "roomsOk",
		showOk: true
	}
}

window.addEvent("domready", function() {
  var t0 = (new Date()).getTime();
  initSearcher();
  var t1 = (new Date()).getTime();
  log("picker.domready finished in " + (t1 - t0) + "msecs");
});
