define([
    'jquery',
    'Magento_Ui/js/model/messageList',
    'uiRegistry'
], function ($, messageList, Registry) {
    'use strict';

    var PCAUrl = '//services.postcodeanywhere.co.uk/Capture/Interactive/Find/v1.00/json3.ws?callback=?';
	var PCARetrieveUrl = '//services.postcodeanywhere.co.uk/Capture/Interactive/Retrieve/v1.00/json3.ws?callback=?';
	var PCAKey = 'UH64-GK52-HE47-YY84';
	var _ip = 'TEST';
	var ShippingSelector = 'checkout.steps.shipping-step.shippingAddress';
	var ShippingAddressSelector = ShippingSelector+'.shipping-address-fieldset';
	var BillingAddressFormSelector = ShippingSelector+'.billing-address-form';
	var BillingAddressSelector = BillingAddressFormSelector+'.form-fields';
	var AgreementsSelector = '.additional-options .checkout-agreements .checkout-agreement.required input';
	
	var verifier = {
		AddressVerificationCountDone: false,
		OpenRequests: 0,
		PCARequestResult: [],
		AddressIdChosen: null,
		AddressIdToConfirm: null,
		AddressCheckStatus: 0,
		AgreementEventSet: false,
				
		/**
		 * type: 
		 * 	0 = postcode search
		 * 	1 = street search
		 *  2 = street search onblur
		 *  3 = verify on checkout
		 */
		doPCARequest: function(search, country, response, type, element)
		{
			if(!this.AgreementEventSet)
			{
				$(AgreementsSelector).eq(0).click(function() {
					this.validateOnAgreementsAccept()
				}.bind(this));
				
				this.AgreementEventSet = true;
			}
			
			var data = {
				Key: PCAKey,
				Text: search,
				Container: '',
				Origin: _ip,
				Countries: country,
				Language: 'de'
			};
			
			if(type != 3)
			{
				data.Limit = (type == 0 ? 50 : (type == 1 ? 10 : 1));
			}
			
			$.ajax( {
				url: PCAUrl,
				dataType: (type != 3 ? 'json' : 'jsonp'),
				data: data,
				success: function(data) {
					switch(type) {
						case 0: this.resolvePostcodes(data, response); break;
						case 1:	this.resolveStreets(data, response); break;
						case 2: this.verifyStreet(data, response, element); break;
						case 3: this.verifyOnCheckout(data, search); break;
					}
				}.bind(this)				
			});
		},
		
		resolvePostcodes: function(data, response)
		{
			if(typeof data.Items !== 'undefined')
			{
				if(data.Items.length > 0)
				{
					for(var i in data.Items)
					{
						if(data.Items[i].Type == 'Postcode')
						{
							var cfrArr = data.Items[i].Description.split(' - ');
							var number = parseInt(cfrArr.pop());
							var cityFromResponse = cfrArr.join(' - ');
							var labelText = data.Items[i].Text+' '+cityFromResponse;
							
							while(typeof(this.PCARequestResult[number]) !== 'undefined')
							{
								number++;
							}
							
							this.PCARequestResult[number] = {
									label: labelText, 
									value: data.Items[i].Text, 
									id: data.Items[i].Id, 
									city: cityFromResponse};
						}
					}
				}
			}
			
			this.OpenRequests--;
			if(this.OpenRequests == 0)
			{
				this.PCARequestResult.reverse();
				var arr = [];
				
				for(var i = 0; i < this.PCARequestResult.length; i++)
				{
					if(typeof(this.PCARequestResult[i]) !== 'undefined')
					{
						arr.push(this.PCARequestResult[i]);
					}
				}

				response(arr);
				this.PCARequestResult = [];
			}
		},
		
		resolveStreets: function(data, response) {
			var results = [];
			
			if(typeof data.Items !== 'undefined')
			{
				if(data.Items.length > 0)
				{
					for(var i in data.Items)
					{
						if(data.Items[i].Type == 'Address')
						{
							var cfrArr = data.Items[i].Description.split(' ');
							var postcode = cfrArr.shift();
							var city = cfrArr.join(' ');
							var label = data.Items[i].Text+' - '+postcode+' '+city;
							
							cfrArr = data.Items[i].Text.split(' ');
							var housenumber = cfrArr[cfrArr.length - 1];
							cfrArr.pop();
							var street = cfrArr.join(' ');
							results.push({type: 'Address', label: label, value: street, id: data.Items[i].Id, housenumber: housenumber, postcode: postcode, city: city});
						}
						else if(data.Items[i].Type == 'Street')
						{
							var cfrArr = data.Items[i].Description.split(' - ');
							cfrArr.pop();
							cfrArr = cfrArr.join(' - ').split(' ');
							var postcode = cfrArr.shift();
							var city = cfrArr.join(' ');
							var label = data.Items[i].Text+' - '+postcode+' '+city;
							results.push({type: 'Street', label: label, value: data.Items[i].Text, postcode: postcode, city: city});
						}
					}
				}
			}
			
			response(results);
		},
		
		verifyStreet: function(data, streetEntered, element) {
			var results = [];
			
			if(typeof data.Items !== 'undefined')
			{
				var correct = true;
				var street = '';
				var addressId = null;
				
				if(data.Items.length > 0)
				{
					//check first item
					if(data.Items[0].Type == 'Address')
					{
						var cfrArr = data.Items[0].Text.split(' ');
						cfrArr.pop();
						street = cfrArr.join(' ');
						
						addressId = data.Items[0].Id;
					}
					else if(data.Items[0].Type == 'Street')
					{
						street = data.Items[0].Text;
					}
					
					//check if street is same, three quater should be ok
					var len = Math.floor(streetEntered.length * 3/4);
					if(street.length >= len)
					{
						for(var i = 0; i < len; i++)
						{
							correct = correct && street.toLowerCase().charAt(i) == streetEntered.toLowerCase().charAt(i);
						}
					}
					else
					{
						correct = false;
					}
				}
				else
				{
					correct = false;
				}
				
				if(!correct)
				{
					if(addressId != null)
					{
						this.AddressIdToConfirm = addressId;
					}
					
					this.showAddressHint(2, street, element);
				}
			}
		},
		
		validate: function () {
            var isValid = true; //Put your validation logic here

            //check billing form data
            let billingForm = Registry.get(BillingAddressFormSelector);
            billingForm.source.trigger('billingAddressshared.data.validate');

            if(billingForm.source.get('params.invalid') && !billingForm.isAddressDetailsVisible())
        	{
            	isValid = false;
        	}

            if (!isValid) {
                //messageList.addErrorMessage({ message: $.mage.__('a possible failure message ...  ') });
            }

            return isValid;
        },
		
        getFormToCheckSelector: function() {
        	return Registry.get(ShippingSelector).isShippingSameAsBilling()
        		? BillingAddressSelector
        		: ShippingAddressSelector;
        },
        
		//run address check on terms accept
		validateOnAgreementsAccept: function() {
			this.addressCheckStatus = 1;
			
			var formToCheck = this.getFormToCheckSelector();

			var countryId = Registry.get(formToCheck+'.country_id').value();
									
			if(countryId == 'DE' || countryId == 'AT')
			{				
				var postcode = Registry.get(formToCheck+'.postcode').value();
				
				this.doPCARequest(postcode, countryId, null, 3);
			}
		},
				
        verifyOnCheckout: function(data, postcode) {
			//check if postcode correct
			if(typeof data.Items !== 'undefined')
			{
				var formToCheck = this.getFormToCheckSelector();
				var city = Registry.get(formToCheck+'.city').value().trim();				
				var id = '';

				if(data.Items.length > 0)
				{
					var postcodeFound = false;
					
					for(var i = 0; i < data.Items.length; i++)
					{
						if(data.Items[i].Type == 'Postcode')
						{
							postcodeFound = true;
							
							id = data.Items[i].Id;

							if(postcode == data.Items[i].Text)
							{
								//postcode correct
								var cfrArr = data.Items[i].Description.split(' - ');
								cfrArr.pop();
								var cityFromResponse = cfrArr.join(' - ');

								//check city
								if(cityFromResponse.length == 0 || (city.length > 0 && cityFromResponse == city))
								{
									//city correct, or not checkable (cityFromResponse.length == 0)
									this.addressCheckStatus = 0;
								}
								else 
								{
									//city incorrect
									this.showAddressHint(1, cityFromResponse, Registry.get(formToCheck+'.postcode'));
								}
							}
							else
							{
								//postcode incorrect
								this.showAddressHint(0, 0, Registry.get(formToCheck+'.postcode'));
							}

							break;
						}
					}
					
					if(!postcodeFound)
					{
						this.showAddressHint(0, 0, Registry.get(formToCheck+'.postcode'));
					}
				}
				
				if(!this.AddressVerificationCountDone && this.AddressIdChosen != null)
				{
					//indicate valid address chosen (eg. payable)
					$.ajax({
						url: PCARetrieveUrl,
						dataType: "jsonp",
						data: {
							key: PCAKey,
							id: this.AddressIdChosen
						}});
					
					this.AddressVerificationCountDone = true;
				}
			}
		},
		
		showAddressHint: function(type, cityHint, element)
		{
			var postcode = element.getPostcode().val();
			var city = element.getCity().val();
			var country = element.getCountry();
			var street = element.getStreet().val().trim();
			var self = this;
						
			if(type == 0)
			{
				$('<div><p>'+$.mage.__('Die eingegebene Postleitzahl könnte im ausgewählten Land nicht verfügbar sein. Bitte überprüfen Sie Ihre Eingabe.')+'</p>'+
						'<p><strong>'+$.mage.__('Postleitzahl')+':</strong>&nbsp;<span>'+postcode+'</span><br>'+
						'<strong>'+$.mage.__('Land')+':</strong>&nbsp;<span>'+country+'</span><br></p></div>').modal({
							appendTo: 'body',
							autoOpen: true});
			}
			if(type == 1)
			{
				$('<div><p>'+$.mage.__('Die eingegebene Stadt könnte nicht zur angegebenen Postleitzahl passen. Bitte überprüfen Sie Ihre Eingabe.')+'</p>'+
						'<p><strong>'+$.mage.__('Postleitzahl')+':</strong>&nbsp;<span>'+postcode+'</span><br>'+
						'<strong>'+$.mage.__('Ort')+':</strong>&nbsp;<span>'+city+'</span><br></p>'+
						'<p>'+$.mage.__('Meinten sie')+'&nbsp;<strong>'+cityHint+'?</strong></p></div>').modal({
							appendTo: 'body',
							autoOpen: true,
							buttons: [{
							    text: $.mage.__('Schließen'),
							    class: '',
							    click: function () {
							        this.closeModal();
							    }
							},{
							    text: $.mage.__('Vorschlag übernehmen'),
							    class: '',
							    click: function () {							    	
							    	this.closeModal();
							    	
							    	element.getCity().val(cityHint);
							    								    	
							    	self.AddressCheckStatus = 0;
							    }
							}]
						});
			}
			if(type == 2)
			{
				$('<div><p>'+$.mage.__('Die eingegebene Straße konnte nicht gefunden werden. Bitte überprüfen Sie ggf. die Schreibweise.')+'</p>'+
						'<p><strong>'+$.mage.__('Ihre Eingabe')+':</strong>&nbsp;<span>'+street+'</span></p>'+
						'<p>'+$.mage.__('Meinten sie')+'&nbsp;<strong>'+cityHint+'</strong>?</p></div>').modal({
					appendTo: 'body',
					autoOpen: true,
					buttons: [{
						    text: $.mage.__('Schließen'),
						    class: '',
						    click: function () {
						        this.closeModal();
						    }
						},{
						    text: $.mage.__('Vorschlag übernehmen'),
						    class: '',
						    click: function () {
						    	this.closeModal();
						    	
						    	element.value(cityHint);
						    	
						    	if(self.AddressIdToConfirm)
					    		{
						    		self.AddressIdChosen = self.AddressIdToConfirm;
					    		}
						    	
						    	self.AddressCheckStatus = 0;
						    }
						},
					]
				 });
			}
		}
	}

    return verifier;
});