/**
 * Create a stateselection widget. As used for address inputs.
 *
 * Calling `.presentationUiStateselection()` creates a stateselection as you can see on all addresses in the storefront and backoffice.
 *
 * ### Examples
 * Render stateselection with respect to a already present country selection.
 *
 * JavaScript:
 *
 *     jQuery.ready({
 *     DOM : true,
 *     plugin : ['de_epages.presentation.ui.stateselection']
 *     }, function ($) {
 *     de_epages('#' + 'ID50A1052BAC1432E11D38_StateDiv').presentationUiStateselection({
 *     "input":{
 *     "name":"State",
 *     "id":"ID50A1052BAC1432E11D38_State",
 *     "mandatoryStar":"*",
 *     "label":"County",
 *     "emptyEntry":"(Select entry)"
 *     },
 *     "countrySelectId" : "ID50A1052BAC1432E11D38_CountryID",
 *     "cssClasses":{
 *     "dialogError" : "DialogError",
 *     "inputField" : "InputField",
 *     "inputLabelling" : "InputLabelling",
 *     "input" : "Text",
 *     "select" : "LongText"
 *     },
 *     "countryId":"276",
 *     "preselectedState":"",
 *     "shopAddressCountryId" : "276",
 *     "formError":false,
 *     "shopRegistrationField":{
 *     "state":{
 *     "isVisibleName":false,
 *     "isMandatoryName":false
 *     },
 *     "countryId":{
 *     "isVisibleName":true,
 *     "isMandatoryName":true}
 *     }
 *     },
 *     "data":{
 *     "300":{"subdivsMandatory":false,"subDivisions":[]},
 *     "372":{"subdivsMandatory":false,"subDivisions":[]},
 *     "484":{"subdivsMandatory":true,"subDivisions":[
 *     {
 *     "code":"BCS",
 *     "language":{
 *     "english":"Baja California Sur",
 *     "native":""
 *     }
 *     },
 *     {
 *     "code":"COA",
 *     "language":{
 *     "english":"Coahuila",
 *     "native":""
 *     }
 *     }
 *     ]}
 *     "840":{"subdivsMandatory":true,"subDivisions":[
 *     {"code":"AL","language":{"english":"Alabama","native":""}}
 *     ]}
 *     }
 *     });
 *     });
 *
 * HTML:
 *
 *     <div class="InputBlock">
 *     <div class="InputLabelling">Country *</div>
 *     <div class="InputField">
 *     <select name="CountryID" class="LongText" id="ID50A1052BAC1432E11D38_CountryID">
 *     <option value="">(Select entry)</option>
 *     <option value="372">Ireland</option>
 *     <option value="484">México (Mexico)</option>
 *     <option value="840">United States</option>
 *     <option value="300">Griech (Greece)</option>
 *     </select>
 *     </div>
 *     </div>
 *
 *     <div id="ID50A1052BAC1432E11D38_StateDiv" class="InputBlock HideElement">
 *     <div class="InputLabelling"></div>
 *     <div class="InputField"></div>
 *     </div>
 *
 *
 * @class jQuery.ui.presentationUiStateselection
 * @extends jQuery.widget
 *
 * @uses jQuery.tmpl
 * @uses jQuery.ui.widget
 * @uses de_epages
 * @uses ep.ui.validate
 * @uses ep.ui.input
 * @since 6.15.0
 */

/**
 * @cfg {Object} input A hash specifying the state input field to be created. (E.g. with keys &quot;name&quot;, &quot;id&quot;,...)
 */

/**
 * @cfg {String} [countrySelectId] Id of the corresponding country select element.
 */

/**
 * @cfg {Object} cssClasses A hash specifying the relevant css classes. (E.g. &quot;dialogError&quot;, &quot;inputField&quot;,...)
 */

/**
 * @cfg {String} [countryId] Id of selected country.
 */

/**
 * @cfg {String} [preselectedState] Code of preselected state.
 */

/**
 * @cfg {String} shopAddressCountryId Id of country of the shop address.
 */

/**
 * @cfg {Boolean} formError Boolean indicating whether this state selection caused a formError.
 */

/**
 * @cfg {Object} shopRegistrationField Hash specifying whether state/country selection is visible/mandatory for the shop.
 */

/**
 * @cfg {Object} data Data hash of the countries and their states.
 */

/**
 * See `jQuery.ui.presentationUiStateselection` for details.
 *
 * @param {Object} [options] A map of additional options to pass to the method.
 * @param {Object} input A hash specifying the state input field to be created. (E.g. with keys &quot;name&quot;, &quot;id&quot;,...)
 * @param {String} [countrySelectId] Id of the corresponding country select element.
 * @param {Object} cssClasses A hash specifying the relevant css classes. (E.g. &quot;dialogError&quot;, &quot;inputField&quot;,...)
 * @param {String} [countryId] Id of selected country.
 * @param {String} [preselectedState] Code of preselected state.
 * @param {String} shopAddressCountryId Id of country of the shop address.
 * @param {Boolean} formError Boolean indicating whether this state selection caused a formError.
 * @param {Object} shopRegistrationField Hash specifying whether state/country selection is visible/mandatory for the shop.
 * @param {Object} data Data hash of the countries and their states.
 *
 * @method presentationUiStateselection
 * @member jQuery
 *
 * @since 6.15.0
 */

define( "de_epages/presentation/ui/stateselection", [
	"jquery",
	"ep",
	"de_epages",
	"$tmpl!./stateselection",

	"jquery/ui/widget",
	"ep/ui/validate",
	"ep/ui/input"
], function ( $, ep, de_epages, tmplStateselection ) {

	// The widget.
	$.widget('ui.presentationUiStateselection', {

		options : {},

		_create : function () {
			var self = this,
					o = self.options;

			// Merge in options from data attribute.
			$.extend(true, o, $.parseJSON(self.element.attr('data-de_epages-presentation-ui-stateselection') || "null"));

			// Init *change* listener on corresponding *country* *select* element.
			self.countrySelect = $('#' + o.countrySelectId).on('change.presentationUiStateselection', $.proxy(self, '_onCountrySelect'));

			// Init input containers.
			o.cssClasses.inputLabelling && (self.inputLabelling = self.element.find('.' + o.cssClasses.inputLabelling));
			self.inputField = (o.cssClasses.inputField && self.element.find('.' + o.cssClasses.inputField)) || self.element;

			// Trigger initial rendering by setting *countryId*.
			var initalCountryID = o.countryId ? o.countryId : self.countrySelect.val();
			self._setOption('countryId', initalCountryID, true);
		},

		_setOption : function (key, value, calledByCreate) {
			if (key === 'countryId') {
				var self = this,
						o = self.options;

				// In case we already luckily guessed the countryId before, we do nothing.
				if (!calledByCreate && o.countryId === value) {
					return;
				}
				this._superApply(arguments);

				// If there is no country selected we assume the country to be equal to the shop's country.
				if (!(o.countryId && self.countrySelect.length && o.shopRegistrationField.countryId.isVisibleName)) {
					o.countryId = o.shopAddressCountryId;
				}

				// Render input with newly selected *countryId*.
				if (o.countryId !== '' ) {
					self._render();
				}
			}
		},

		_onCountrySelect : function (event) {
			this._setOption('countryId', this.countrySelect.children(':selected').val());
		},

		_render : function () {
			var self = this,
					o = self.options,
					hasSubDivisions = false,
					stateIsMandatory = false,
					stateIsDisabled = $('#' + o.input.id).prop('disabled'),
					countryData;

			// Clean the plate.
			if (self.input) {self.input.remove();}
			if (self.inputLabelling) {self.inputLabelling.empty();}

			if ( o.data[o.countryId] ) {
				countryData = o.data[o.countryId];
				stateIsMandatory = o.shopRegistrationField.state.isMandatoryName || countryData.subdivsMandatory;
				hasSubDivisions = true;
			}

			if ( (stateIsMandatory || o.shopRegistrationField.state.isVisibleName) && hasSubDivisions ) {
				// Render *input* template.
				self.input = tmplStateselection({
						country: countryData
					}, o)
					.prop({
						disabled: stateIsDisabled
					})
					.uiValidate({
						valid: !o.formError,
						required: stateIsMandatory
					});

				// Reset *preselectedState* option. Only used for initial *_create*.
				// E.g. the user is redirected to the form and already entered a state before.
				self._setOption('preselectedState', '');

				// Set *inputLabelling*.
				if (self.inputLabelling) {
					self.inputLabelling.append(o.input.label + (stateIsMandatory ? (' ' + o.input.mandatoryStar) : ''));
				}

				// Add *input* to *inputField*.
				self.inputField.empty()
					.append(self.input);

				// Show *element*.
				self.element.removeClass('HideElement');
			}
			else {
				// Hide *element*.
				self.element.addClass('HideElement');
				// Add hidden input to overwrite previously value on the server-side.
				// This could/should be handled by the server, but currently is not.
				self.input = $('<input type="hidden"/>').attr({
					name : o.input.name,
					id : o.input.id,
					value : ''
				});
				self.input.appendTo(self.inputField);
			}
		},

		destroy : function () {
			this.countrySelect && this.countrySelect.length && this.countrySelect.off('change.presentationUiStateselection');
			this.inputLabelling && this.inputLabelling.empty();
			this.input && this.input.remove();
			this._superApply(arguments);
		}

	});

	return de_epages;

});