(function() {

var $ = document.id;


this.DirectorySearchForm = new Class({

	Implements: [Events, Options],

	options: {
		inputElements: {
			directory: "",
			subDirectory: "",
			country: "",
			zone: "",
			button: ""
		},
		serviceUrl: "http://www.wellbeing.ie/index.php?id=986",
		form: ""
	},

	/* the form element */
	form: false,

	/* The directory dropdown/input */
	directory: false,

	/* The sub-directory dropdown */
	subDirectory: false,

	/* The country dropdown */
	country: false,

	/* The zone dropdown */
	zone: false,

	/* the search button */
	button: false,

	/* The url we use to retrieve data from */
    //A.: bug fix, initial value must be set to use in json request
	serviceUrl: "http://www.wellbeing.ie/index.php?id=986",

	/* Local cache for sub-directories */
	subDirectoryCache: {},

	/* Local cache for countries */
	countryCache: {},

	/* Local cache for zones */
	zoneCache: {},



	/* initializes the component */
	initialize: function(options)
	{
		this.setOptions(options);
        //A.: this won't work because instance initialized only once
		//this.serviceUrl = this.options.serviceUrl;

		if ($(this.options.form))
		{
			this.form = $(this.options.form);
		}
		else
		{
			throw "DirectorySearchForm: No Form Found";
		}

		if ($(this.options.inputElements.directory))
		{
			this.directory = $(this.options.inputElements.directory);
		}
		else
		{
			throw "DirectorySearchForm: No Directory Input";
		}

		if ($(this.options.inputElements.subDirectory))
		{
			this.subDirectory = $(this.options.inputElements.subDirectory);
		}
		else
		{
			throw "DirectorySearchForm: No Sub-Directory Input";
		}


		if ($(this.options.inputElements.country))
		{
			this.country = $(this.options.inputElements.country);
		}
		else
		{
			throw "DirectorySearchForm: No Country Input";
		}

		if ($(this.options.inputElements.zone))
		{
			this.zone = $(this.options.inputElements.zone);
		}
		else
		{
			throw "DirectorySearchForm: No Zone Input";
		}

		if ($(this.options.inputElements.button))
		{
			this.button = $(this.options.inputElements.button);
		}
		else
		{
			throw "DirectorySearchForm: No Search Button";
		}

		/* add change event to the directory */
		if (this.directory && this.directory.get("tag") == "select")
		{
			this.directory.addEvent("change", this.directoryInputChangeEvent.bindWithEvent(this));
		}

		/* add change event to the sub-directory */
		if (this.subDirectory.get("tag") == "select")
		{
			this.subDirectory.addEvent("change", this.subDirectoryInputChangeEvent.bindWithEvent(this));
		}
		else
		{
			throw "DirectorySearchForm: Sub-Directory input must be a dropdown";
		}

		if (this.country.get("tag") == "select")
		{
			this.country.addEvent("change", this.countryInputChangeEvent.bindWithEvent(this));
		}

		this.button.addEvent("click", this.searchButtonClickEvent.bindWithEvent(this));

	},


	/* Responsible for updating the sub directory dropdown */
	setSubDirectories: function(subDirectories)
	{
		this.subDirectory.empty();

		/* cycle over the sub-directories and add each one to the dropdown */
		subDirectories.each(function(subDirectory) {
			new Element("option", {text: subDirectory.title, value: subDirectory.uid}).inject(this.subDirectory, "bottom");
		}, this);

		/* add an informational/instructional element at the top */
		if (subDirectories.length > 0)
		{
			new Element("option", {text: "Please Choose...", value: "", selected: "selected"}).inject(this.subDirectory, "top");
		}
		else
		{
			new Element("option", {text: "None Available", value: "", selected: "selected"}).inject(this.subDirectory, "top");
			/*
			 * now we should really download some countries for the directory so pseudo-fire
			 * the change even on the sub directory dropdown
			 */
			this.subDirectoryInputChangeEvent({target: this.subDirectory});
		}

	},


	/* Responsible for updating the country dropdown */
	setCountries: function(countries)
	{
		this.country.empty();

		/* cycle over the countries and add each one to the dropdown */
		countries.each(function(country) {
			new Element("option", {text: country.cn_short_en, value: country.uid}).inject(this.country, "bottom");
		}, this);

		/* add an information/instructional element at the top */
		if (countries.length > 0)
		{
			new Element("option", {text: "Please Choose...", value: "", selected: "selected"}).inject(this.country, "top");
		}
		else
		{
			new Element("option", {text: "None Available", value: "", selected: "selected"}).inject(this.country, "top");
		}
	},


	/* Responsible for updating the zone dropdown */
	setZones: function(zones)
	{
		this.zone.empty();

		/* cycle over the zones and add each one to the dropdown */
		zones.each(function(zone) {
			new Element("option", {text: zone.zn_name_local, value: zone.uid}).inject(this.zone, "bottom");
		}, this);

		/* add an information/instruction element at the top */
		if (zones.length > 0)
		{
			new Element("option", {text: "Please Choose...", value: "", selected: "selected"}).inject(this.zone, "top");
		}
		else
		{
			new Element("option", {text: "None Available", value: "", selected: "selected"}).inject(this.zone, "top");
		}
	},


	/* INPUT ELEMENT EVENT HANDLERS */

	/* Handles change events in the directory dropdown */
	directoryInputChangeEvent: function(e)
	{
		var target = $(e.target);

		var directoryId = target.get("value");

		/* clear out the sub-directory input */
		this.subDirectory.empty();

		/* if there is a country dropdown then clear it */
		if (this.country && this.country.get("tag") == "select")
		{
			this.country.empty();
			new Element("option", {text: "None Available", value: "", selected: "selected"}).inject(this.country, "top");
		}

		/* if there is a zone dropdown then clear it */
		if (this.zone && this.zone.get("tag") == "select")
		{
			this.zone.empty();
			new Element("option", {text: "None Available", value: "", selected: "selected"}).inject(this.zone, "top");
		}

		/* check for cached sub-directories */
		if (typeof this.subDirectoryCache[directoryId] != "undefined")
		{
			/* load new sub-directories */
			this.setSubDirectories(this.subDirectoryCache[directoryId]);
		}
		else
		{
			/* use existing sub-directories */
			this.downloadSubDirectories(directoryId);
		}
	},


	/* Handles a change event in the sub-directory dropdown */
	subDirectoryInputChangeEvent: function(e)
	{
        var target = $(e.target);
		var subDirectoryId = this.subDirectory.get("value");
		var directoryId = this.directory.get("value");

		if (this.country && this.country.get("tag") == "select")
		{

			/* check for cached countries */
			if (typeof this.countryCache[directoryId] != "undefined")
			{
				this.setCountries(this.countryCache[directoryId])
			}
			else if (typeof this.countryCache[subDirectoryId] != "undefined")
			{
				this.setCountries(this.countryCache[subDirectoryId])
			}
			/* download countries */
			else
			{
                this.country.empty();
				new Element("option", {text: "Loading...", value: ""}).inject(this.country, "top");
				this.downloadCountries(directoryId, subDirectoryId);
			}
		}
		else if (this.country)
		{
            /* download zones */
			this.zone.empty();
			new Element("option", {text: "Loading...", value: ""}).inject(this.zone, "top");
			var countryId = this.country.get("value");
			this.downloadZones(directoryId, subDirectoryId, countryId);
		}
		else
		{
            /* this should not happen as we need a country input of some sort */
			throw "DirectorySearchForm: No Country Input Found.";
		}
	},

	/* handles a change event in the country dropdown */
	countryInputChangeEvent: function(e)
	{
        var target = $(e.target);
		var subDirectoryId = this.subDirectory.get("value");
		var directoryId = this.directory.get("value");
		var countryId = target.get("value");
		this.downloadZones(directoryId, subDirectoryId, countryId);
	},


	/* handles a click event on the search button */
	searchButtonClickEvent: function(e)
	{
		/* we require a direcory be selected, and that is all */
		if (this.directory.get("value") == "" || this.directory.get("value") == 0)
		{
			alert("Please choose a directory");
		}
		this.form.submit();
	},


	/* SERVER REQUESTS */


	/* Responsible for downloading sub-directories for the given directoryId */
	downloadSubDirectories: function(directoryId)
	{
		/* add a loading message to the sub-directory input */
		var data = [{title: "Loading", uid: ""}];
		this.subDirectory.empty();
		new Element("option", {text: "Loading...", value: ""}).inject(this.subDirectory, "bottom");

		new Request.JSON({
			url: this.serviceUrl,
			onSuccess: this.downloadSubDirectoriesResponseHandler.bindWithEvent(this)
		}).get({tx_p4wbdirectory_jsonfeed: {
			get: "sub-directories",
			directoryId: directoryId
		}});
	},

	/* Responsible for downloading countries for the given directoryId and/or subDirectoryId */
	downloadCountries: function(directoryId, subDirectoryId)
	{
		new Request.JSON({
			url: this.serviceUrl,
            onFailure: function(xhr){ console.log("onFailure"); },
			onSuccess: this.downloadCountriesResponseHandler.bindWithEvent(this)
		}).get({tx_p4wbdirectory_jsonfeed: {
			get: "countries",
			directoryId: directoryId,
			subDirectoryId: subDirectoryId
		}});
	},


	/* Responsible for downloading zones for the given values */
	downloadZones: function(directoryId, subDirectoryId, countryId)
	{
        new Request.JSON({
			url: this.serviceUrl,
            onFailure: function(xhr){
                console.log(xhr.getAllResponseHeaders());
                console.log(xhr.status, xhr.statusText, xhr.responseText);},
			onSuccess: this.downloadZonesResponseHandler.bindWithEvent(this)
		}).get({tx_p4wbdirectory_jsonfeed: {
			get: "zones",
			directoryId: directoryId,
			subDirectoryId: subDirectoryId,
			countryId: countryId
		}});
	},




	/* SERVER RESPONSE HANDLERS */


	/* Receives the server response when loading sub-directories */
	downloadSubDirectoriesResponseHandler: function(responseJSON, responseText)
	{
		/* decode and check the response */
		var response = JSON.decode(responseText);
		if (response.status == 0)
		{
			throw response.message;
		}

		/* get the sub-directories from the response */
		var subDirectories = response.data;

		/* cache the sub-directories */
		this.subDirectoryCache[response.directoryId] = subDirectories;

		/* set the sub-directories to the subDirectory input */
		this.setSubDirectories(subDirectories);

	},

	/* Receives the server response when loading countries */
	downloadCountriesResponseHandler: function(responseJSON, responseText)
	{
		var response = JSON.decode(responseText);
		if (response.status == 0)
		{
			throw response.message;
		}

		/* get the countries */
		var countries = response.data;

		/* decide what to cache the countries against, either directory or sub-directory */
		var directoryId = response.subDirectoryId;
		if (directoryId == 0)
		{
			directoryId = response.directoryId;
		}

		/* cache the countries */
		this.countryCache[directoryId] = countries;

		/* set the countries to the county input */
		this.setCountries(countries);

	},

	/* Receives the server response when loading zones */
	downloadZonesResponseHandler: function(responseJSON, responseText)
	{
        var response = JSON.decode(responseText);
		if (response.status == 0)
		{
			throw response.message;
		}

		var zones = response.data;

		/* decide what to cache the zones against, either directory or sub-directory followed by country */
		var directoryId = response.subDirectoryId;
		if (directoryId == 0)
		{
			directoryId = response.directoryId;
		}

		/* cache the zones */
		if (typeof this.zoneCache[directoryId] == "undefined")
		{
			this.zoneCache[directoryId] = {};
		}
		this.zoneCache[directoryId][this.country.get("value")] = zones;

		/* set the zones to the zone input */
		this.setZones(zones);
	}




});

})();
