
// Indicator for lists, that shows for current item, that it is not selectable.
var NOT_SELECTABLE_ITEM_INDICATOR = "--";

// Submit form by id.
//    id - id of the form.
function submitForm(formId) { 
  var formElement;

  formElement = $(formId);  
  if (formElement) {
    formElement.submit() ;
  }
}

// Get XMLHttpRequest (cross-browser version).
//    result - XMLHttpRequest object.
function getXMLHttpRequest(){
  var xmlhttp;
  
  try {
    xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
  } catch (e) {
    try {
      xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
    } catch (e1) {
      xmlhttp = false;
    }
  }
  if (!xmlhttp && typeof XMLHttpRequest!='undefined') {
    xmlhttp = new XMLHttpRequest();
  }
  return xmlhttp;
}

// Ask SOAP-service for information and obtain response text in the IN-parameter of callback function.
//    url - URL of the service (must contain name of the service).
//    name - name of the service.
//    xml - request XML.
//    callback - callback function; must contain one input parameter to transfer response text.
function askSoapService(url, name, xml, callback) {
  var xmlHttpReq;

  xmlHttpReq = getXMLHttpRequest(); 
     
  xmlHttpReq.onreadystatechange = function() {   
    if (xmlHttpReq.readyState == 4) {  
        if(xmlHttpReq.status == 200) {        
            callback(xmlHttpReq.responseText);
          }
      }  
  }
   
    xmlHttpReq.open('POST', url, true);
  
  // Headers
  xmlHttpReq.setRequestHeader('Content-Type','text/xml');
  xmlHttpReq.setRequestHeader('SOAPAction', name);
  
  xmlHttpReq.send(xml);
  
}

// Convert string with XML to XML-object (cross-browser version).
//    string - string with XML.
//    result - XML-object/
function convertStringToXml(string) {
  var xmlDoc;
  var parser;
  
  if (window.DOMParser) {
    parser = new DOMParser();
    xmlDoc = parser.parseFromString(string, "text/xml");
  } else {
    // For Internet Explorer
    xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
    xmlDoc.async = "false";
    xmlDoc.loadXML(string);
  }
  return xmlDoc;
}

// Get XML elements by tag name with attention to prefix (cross-browser version).
//    xmlDocument - XML-object. 
//    prefix - prefix without trailing ":".
//    tagName - name of the tag.
//    result - array of the elements.
function getElementsByTagNameAndPrefix(xmlDocument, prefix, tagName) {
  var result;

  result = xmlDocument.getElementsByTagName(tagName);  
  if (result && result.length == 0) {
    result = xmlDocument.getElementsByTagName(prefix + ':' + tagName);  
  } 
  return result;
}

// Get text from child node.
//    parentNode - parent node (Object).
//    childNodeName - child node name (String).
//    result - string with the text.
function getChildNodeText(parentNode, childNodeName) {
  var child;
  
  child = parentNode.getElementsByTagName(childNodeName); 
  return child[0].childNodes[0].nodeValue;    
}

// Create an <option> element.
//    text - text for the <option>.
//    value - value for the <option>.
//    isDefaultSelected - is <option> selected by default
//    isSelected - is <option> selected
//    result - just created <option>.
function createOption(text, value, isDefaultSelected, isSelected) {
	var option;

	option = document.createElement("option");
	option.appendChild(document.createTextNode(text));
	option.setAttribute("value", value);

	// Check if value starts with indicator NOT_SELECTABLE_ITEM_INDICATOR
	if (text.startsWith(NOT_SELECTABLE_ITEM_INDICATOR)) {
		option.disabled = true;
	}

	if (!option.disabled && isDefaultSelected) {
		option.defaultSelected = true;
	} else if (isSelected) {
		option.selected = true;
	}

	return option;
}

// Add new <option> to the <select> element.
//    listbox - <select> element.
//    text - text for the <option>.
//    value - value for the <option>.
//    isDefaultSelected - is <option> selected by default
//    isSelected - is <option> selected
//    result - just created <option>.
function addOption(listbox, text, value, isDefaultSelected, isSelected) {
	var option = createOption(text, value, isDefaultSelected, isSelected);
	listbox.appendChild(option);
	return option;	
}

// Add new <option> to the beginning of the <select> element.
//    listbox - <select> element.
//    text - text for the <option>.
//    value - value for the <option>.
//    isDefaultSelected - is <option> selected by default
//    isSelected - is <option> selected
//    result - just created <option>.
function insertFirstOption(listbox, text, value, isDefaultSelected, isSelected) {
	var option = createOption(text, value, isDefaultSelected, isSelected);
	listbox.insertBefore(option, listbox.firstChild);	
	if (isSelected){
		listbox.options[0].selected = true;
	}
	return option;	
}


// Fast and safe function for clearing options in <select> element.
//    elementId - id of the <select> element.
function fastClearOptions(elementId) {
 var element = $(elementId);
  while (element.lastChild)
   element.removeChild(element.lastChild);
 return element;
 /* this shit copies clone elenent that is NOT equal to native
  example: list_box_ID123(NATIVE) != list_box_ID654(CLONE)
 var selectParentNode = element.parentNode;
 var newElement = element.cloneNode(false); // Make a shallow copy
 selectParentNode.replaceChild(newElement, element);
 return newElement;*/
}

// Load cities list with geo information.
//    idRegion - id of the region.
//    listBox - HTML-element "select", where to put found cities.
//    callback - callback function, that retrieves count of found cities
function getCitiesListByRegionIdWithGeoInfo(idRegion, listBox, callback) {
  var internalCallback;
  var xml;

  internalCallback = function (responseText) {
    var cities;
    var city;
    var cityName;
    var id;
    var hasGeoInformation;
    var option;
    var xmlDocument;

    xmlDocument = convertStringToXml(responseText);

	if (!xmlDocument) {	
      return;
    }

    cities = getElementsByTagNameAndPrefix(xmlDocument, 'ns2', 'CitiesList');

    if (cities) {

		for (var i = 0; i < cities.length; ++i) {
			city = cities[i];
			if (city.hasChildNodes()) {
			  cityName = getChildNodeText(city, 'name');
			  id = getChildNodeText(city, 'id');
			  hasGeoInformation = getChildNodeText(city, 'hasGeoInformation');
			  option = addOption(listBox, cityName, id, false, false);
			  option.setAttribute("hasgeoinformation", hasGeoInformation);
			} // if (city.hasChildNodes())
		} // for
		callback(cities.length);
    } // if (cities)

  }
  
  xml = '<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">' + 
        ' <SOAP-ENV:Header/>' + 
        ' <SOAP-ENV:Body>' + 
        '  <getCitiesListByRegionIdWithGeoInfo xmlns="urn:singles:operations">' + 
        '   <regionId>' + idRegion + '</regionId>' + 
        '  </getCitiesListByRegionIdWithGeoInfo>' + 
        ' </SOAP-ENV:Body>' + 
        '</SOAP-ENV:Envelope>'; 
  
            
  askSoapService('/ws/GeoService', 'GeoService', xml, internalCallback);  
  
}

// Load cities list with geo information.
//    idCounty - id of the county.
//    listBox - HTML-element "select", where to put found cities.
//    callback - callback function, that retrieves count of found cities
function getCitiesListByCountyIdWithGeoInfo(idCounty, listBox, callback) {
  var internalCallback;
  var xml;

  internalCallback = function (responseText) {
    var cities;
    var city;
    var cityName;
    var id;
    var hasGeoInformation;
    var option;
    var xmlDocument;

    xmlDocument = convertStringToXml(responseText);

	if (!xmlDocument) {	
      return;
    }

    cities = getElementsByTagNameAndPrefix(xmlDocument, 'ns2', 'CitiesList');

    if (cities) {

		for (var i = 0; i < cities.length; ++i) {
			city = cities[i];
			if (city.hasChildNodes()) {
			  cityName = getChildNodeText(city, 'name');
			  id = getChildNodeText(city, 'id');
			  hasGeoInformation = getChildNodeText(city, 'hasGeoInformation');
			  option = addOption(listBox, cityName, id, false, false);
			  option.setAttribute("hasgeoinformation", hasGeoInformation);
			} // if (city.hasChildNodes())
		} // for
		callback(cities.length);
    } // if (cities)

  }
  
  xml = '<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">' + 
        ' <SOAP-ENV:Header/>' + 
        ' <SOAP-ENV:Body>' + 
        '  <getCitiesListByCountyIdWithGeoInfo xmlns="urn:singles:operations">' + 
        '   <countyId>' + idCounty + '</countyId>' + 
        '  </getCitiesListByCountyIdWithGeoInfo>' + 
        ' </SOAP-ENV:Body>' + 
        '</SOAP-ENV:Envelope>'; 
  
            
  askSoapService('/ws/GeoService', 'GeoService', xml, internalCallback);  
  
}

// Load counties list.
//    idRegion - id of the region.
//    listBox - HTML-element "select", where to put found counties.
//    callback - callback function, that retrieves count of found counties
function getCountiesList(idCountry, idRegion, listBox, callback){
  var internalCallback;
  var xml;

  internalCallback = function (responseText) {
    var counties;
    var county;
    var countyName;
    var id;
    var option;
    var xmlDocument;

    xmlDocument = convertStringToXml(responseText);
	
    if (!xmlDocument)
      return;

    counties = getElementsByTagNameAndPrefix(xmlDocument, 'ns2', 'CountiesList');

	if (counties) {
		for (var i = 0; i < counties.length; i++) {
			county = counties[i];
			if (county.hasChildNodes()) {
			  countyName = getChildNodeText(county, 'name');
			  id = getChildNodeText(county, 'id');
			  option = addOption(listBox, countyName, id, false, false);
			} // if (county.hasChildNodes())
		} // for
		callback(counties.length);
    } // if (counties)
  }

  xml = '<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">' +
        ' <SOAP-ENV:Header/>' +
        ' <SOAP-ENV:Body>' +
        '  <getCountiesList xmlns="urn:singles:operations">' +
        '   <countryId>' + idCountry + '</countryId>' +
		'   <regionId>' + idRegion  + '</regionId>' +
        '  </getCountiesList>' +
        ' </SOAP-ENV:Body>' +
        '</SOAP-ENV:Envelope>';

  askSoapService('/ws/GeoService', 'GeoService', xml, internalCallback);
}

// Load cities list.
//    idRegion - id of the region.
//    listBox - HTML-element "select", where to put found cities.
//    callback - callback function, that retrieves count of found cities
function getCitiesListByCountryId(idCountry, listBox, callback) {
  var internalCallback;
  var xml;

  internalCallback = function (responseText) {
    var cities;
    var city;
    var cityName;
    var id;
    var hasGeoInformation;
    var option;
    var xmlDocument;

    xmlDocument = convertStringToXml(responseText);
    if (!xmlDocument) {
      return;
    }

    cities = getElementsByTagNameAndPrefix(xmlDocument, 'ns2', 'CitiesList');
    if (cities) {

		for (var i = 0; i < cities.length; ++i) {
			city = cities[i];
			if (city.hasChildNodes()) {
			  cityName = getChildNodeText(city, 'name');
			  id = getChildNodeText(city, 'id');
			  hasGeoInformation = getChildNodeText(city, 'hasGeoInformation');
			  option = addOption(listBox, cityName, id, false, false);
			  option.setAttribute("hasgeoinformation", hasGeoInformation);
			} // if (city.hasChildNodes())
		} // for

		callback(cities.length);

    } // if (cities)

  }

  xml = '<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">' +
        ' <SOAP-ENV:Header/>' +
        ' <SOAP-ENV:Body>' +
        '  <getCitiesListByCountryId xmlns="urn:singles:operations">' +
        '   <countryId>' + idCountry + '</countryId>' +
        '  </getCitiesListByCountryId>' +
        ' </SOAP-ENV:Body>' +
        '</SOAP-ENV:Envelope>'; 

  askSoapService('/ws/GeoService', 'GeoService', xml, internalCallback);
}

// Load regions list.
//    idCountry - id of the country.
//    listBox - HTML-element "select", where to put found regions.
//    callback - callback function, that retrieves count of found regions
function getRegionsListByCountryId(idCountry, listBox, callback, listBoxCities, callbackCities) {

  var internalCallback;
  var xml;

  internalCallback = function (responseText) {
    var regions;
    var region;
    var regionName;
    var id;
    var option;
    var xmlDocument;

    xmlDocument = convertStringToXml(responseText);

    if (!xmlDocument) {
      return;
    }

    regions = getElementsByTagNameAndPrefix(xmlDocument, 'ns2', 'RegionsList');

	if (regions.length == 0){
		listBoxCities.options.length = 0;
		listBoxCities.disabled = true;
		getCitiesListByCountryId(idCountry, listBoxCities, callbackCities);
		listBoxCities.disabled = false;
		return;
	}

	if (regions) {
		for (var i = 0; i < regions.length; ++i) {
			region = regions[i];
			if (region.hasChildNodes()) {
			  regionName = getChildNodeText(region, 'name');
			  id = getChildNodeText(region, 'id');
			  option = addOption(listBox, regionName, id, false, false);
			} // if (region.hasChildNodes())
		} // for

		callback(regions.length);
    } // if (regions)
  }

  xml = '<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">' +
        ' <SOAP-ENV:Header/>' +
        ' <SOAP-ENV:Body>' +
        '  <getRegionsListByCountryId xmlns="urn:singles:operations">' +
        '   <countryId>' + idCountry + '</countryId>' +
        '  </getRegionsListByCountryId>' +
        ' </SOAP-ENV:Body>' +
        '</SOAP-ENV:Envelope>';

  askSoapService('/ws/GeoService', 'GeoService', xml, internalCallback);

}

// Debugging function
//    message - message to show at the console.
function debug(message) {
	if (typeof console !== 'undefined' && typeof console.debug !== 'undefined') {
		console.debug.apply(console, [message]);
	}
}

// Preload image.
//    src - url of image.
function preloadImage(src) {
	if (document.images) {
		var image = new Image();
		image.src = src;
	}
}

// Check if number is null or zero.
//    value - string to check.
//    result - true, if string is empty, false - otherwise.
function isNullOrZero(value) {
	return (!value || (value == 0));
}

// Get number of days in month.
//    year - year of month.
//    month
//    result - number of days in month.
function getDaysInMonth(year, month) {
	var date = new Date(year, month, 0);
	return date.getDate();
}
