/* Minification failed. Returning unminified contents.
(1,9): run-time error CSS1031: Expected selector, found '='
(1,9): run-time error CSS1025: Expected comma or open brace, found '='
(3,5): run-time error CSS1030: Expected identifier, found 'controller('
(3,5): run-time error CSS1031: Expected selector, found 'controller('
(3,5): run-time error CSS1025: Expected comma or open brace, found 'controller('
(900,5): run-time error CSS1030: Expected identifier, found 'directive('
(900,5): run-time error CSS1031: Expected selector, found 'directive('
(900,5): run-time error CSS1025: Expected comma or open brace, found 'directive('
(917,2): run-time error CSS1019: Unexpected token, found ')'
(919,5): run-time error CSS1030: Expected identifier, found 'filter('
(919,5): run-time error CSS1031: Expected selector, found 'filter('
(919,5): run-time error CSS1025: Expected comma or open brace, found 'filter('
(928,2): run-time error CSS1019: Unexpected token, found ')'
(930,5): run-time error CSS1030: Expected identifier, found 'directive('
(930,5): run-time error CSS1031: Expected selector, found 'directive('
(930,5): run-time error CSS1025: Expected comma or open brace, found 'directive('
(948,2): run-time error CSS1019: Unexpected token, found ')'
(950,5): run-time error CSS1030: Expected identifier, found 'directive('
(950,5): run-time error CSS1031: Expected selector, found 'directive('
(950,5): run-time error CSS1025: Expected comma or open brace, found 'directive('
(966,2): run-time error CSS1019: Unexpected token, found ')'
(968,5): run-time error CSS1030: Expected identifier, found 'directive('
(968,5): run-time error CSS1031: Expected selector, found 'directive('
(968,5): run-time error CSS1025: Expected comma or open brace, found 'directive('
(983,2): run-time error CSS1019: Unexpected token, found ')'
(985,5): run-time error CSS1030: Expected identifier, found 'directive('
(985,5): run-time error CSS1031: Expected selector, found 'directive('
(985,5): run-time error CSS1025: Expected comma or open brace, found 'directive('
(1000,2): run-time error CSS1019: Unexpected token, found ')'
(1002,5): run-time error CSS1030: Expected identifier, found 'directive('
(1002,5): run-time error CSS1031: Expected selector, found 'directive('
(1002,5): run-time error CSS1025: Expected comma or open brace, found 'directive('
(1019,2): run-time error CSS1019: Unexpected token, found ')'
(1022,5): run-time error CSS1030: Expected identifier, found 'directive('
(1022,5): run-time error CSS1031: Expected selector, found 'directive('
(1022,5): run-time error CSS1025: Expected comma or open brace, found 'directive('
(1041,5): run-time error CSS1030: Expected identifier, found 'config('
(1041,5): run-time error CSS1031: Expected selector, found 'config('
(1041,5): run-time error CSS1025: Expected comma or open brace, found 'config('
(1051,2): run-time error CSS1019: Unexpected token, found ')'
(1052,1): run-time error CSS1019: Unexpected token, found '('
(1052,11): run-time error CSS1031: Expected selector, found '('
(1052,11): run-time error CSS1025: Expected comma or open brace, found '('
(1227,2): run-time error CSS1019: Unexpected token, found ')'
(1227,3): run-time error CSS1019: Unexpected token, found '('
(1227,4): run-time error CSS1019: Unexpected token, found ')'
 */
var app = angular.module('app');

app.controller('form', ['$location', '$scope', '$q', 'Objection', 'moment', '$window', '$http', '$base64', '$mdDialog', '$rootScope', 'ObjectionConfig',
	function ($location, $scope, $q, objections, moment, $window, $http, $base64, $mdDialog, $rootScope, objectionConfig) {

		// override the js date function toJson to truncate the time portion of the date.
		Date.prototype.toJSON = function () {
			return moment(this).format("YYYY-MM-DD");
		};

		//constants
		const _closeJobStatusConst = 1;
		const _revalJobTypeConst = 1;
		const _suppJobTypeConst = 2;

		$scope.PropertySearchTypeConstants = {
			Address: '1',
			DVRNumber: '2'
		};

		$scope.options = {
			types: ['address'],
			componentRestrictions: { country: 'NZ' }
		};

		$scope.version = moment(new Date()).format('YYYYMMDDhhmmss');

		$scope.AttachmentMaxSize = 50000000;
		$scope.SupportingEvidenceMaxCount = 5;
		$scope.SubmitToken = '';
		$scope.isUploading = false;

		$scope.title = "Residential";
		$scope.upload = '';
		$scope.init = function (Id, Mode, type, ClientId, guid, batchId, objectionFormType, suppNoJobsNoDays) {
			$scope.persisted = {};
			$scope.objectionId = Id;
			$scope.clientId = ClientId;
			$scope.mode = Mode;
			$scope.objectionType = type;
			$scope.displaySubmitPannel = false;
			$scope.showValidationBox = false;
			$scope.duration = '';
			$scope.statusToolTip = '';
			$scope.showSpinner = false;
			$scope.showSaveSpinner = false;
			$scope.requiredOnSubmit = false;
			$scope.submitObjectionSuccessful = false;
			$scope.propertyDetailsLoading = false;
			$rootScope.properties = [];
			$scope.propertyType = '';
			$scope.showReCaptchaIsRequired = false;
			$scope.guid = guid;
			$scope.batchId = batchId;
			$scope.objectionFormType = parseInt(objectionFormType);
			$scope.suppNoJobsNoDays = suppNoJobsNoDays;

			$q.all([
				$scope.loadLookups()
			]).then(function (results) {
				$scope.lookups = results[0].data;
			});

			if ($scope.objectionId !== 0) {
				$q.all([
					$scope.loadObjection()
				]).then(function (results) {
					var objection = results[0].data;
					$scope.setModel(objection);
					$scope.guid = objection.GUID;
					$scope.getAttachments()
				});
			}

			if ($scope.model.propertySearchType === null || !angular.isDefined($scope.model.propertySearchType)) {
				$scope.model.propertySearchType = $scope.PropertySearchTypeConstants.DVRNumber;
			}
		};

		$rootScope.model = {
			propertyAddress: {
				name: '',
				dvrNumber: '',
				propertyAddressComponents: {
					streetNumber: '',
					street: '',
					city: '',
					state: '',
					postCode: '',
					suburb: '',
					unitNumber: ''
				},
				manualEntry: false
			},
			valuationReferenceNumber: '',
			councilPropertyId: '',
			titleNumber: '',
			legalDescription: '',
			fullName: '',
			postalAddress: {
				name: '',
				postalAddressComponents: {
					streetNumber: '',
					street: '',
					city: '',
					state: '',
					postCode: ''
				}
			},
			workPhone: '',
			homePhone: '',
			mobilePhone: '',
			email: '',
			confirmEmail: '',
			lodgerRole: '',
			otherLodgerRole: '',
			groundsForObjecting: {
				propertyValue: false,
				noticeOfValuation: false,
				areaOrDescription: false,
				improvements: false,
				other: false
			},
			landValueCouncil: '',
			landValueEstimated: '',
			improvementsCouncil: '',
			improvementsEstimated: '',
			capitalCouncil: '',
			capitalEstimated: '',
			valuationDate: null,
			reasoningContendedvalues: '',
			landArea: '',
			buildingType: '',
			buildingArea: '',
			noOfBedrooms: '',
			noOfBathrooms: '',
			noOfMainRooms: '',
			constructionMaterial: '',
			otherConstructionMaterial: '',
			buildingCondition: '',
			yearBuilt: '',
			yearExtended: '',
			renovationDesc: '',
			propertyMoreInfo: '',
			supportingEvidences: [],
			attachments: [],
			submited: false,
			propertySearchType: null,
			valorClientId: '',
			valorBatchId: '',
			objectionFormType: '',
			nonSupplementary: false
		};

		$scope.showFormSupEvidence = false;
		$scope.supportingEvidence = {
			salesAddress: {
				name: '',
				salesAddressComponents: {
					streetNumber: '',
					street: '',
					city: '',
					state: '',
					postCode: ''
				}
			},
			salesDate: null,
			salesPrice: '',
			landArea: '',
			buildingArea: '',
			buildingCondition: '',
			leaseAmt: '',
			leaseTerm: '',
			options: '',
			additionalInfo: '',
			leaseTermYears: '',
			leaseTermMonths: ''
		};

		$scope.allowedFileUpload = 'application/pdf,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.openxmlformats-officedocument.wordprocessingml.document';
		$scope.showManualPropertyEntry = false;
		$scope.attachmentsExceededMaxSize = false;
		$scope.ReCaptcha = '';

		/****************Begin Support Evedence*********/

		$scope.addNewEvidence = function () {
			$scope.setFocus = true;

			$scope.model.supportingEvidences.push({
				salesAddress: {
					name: $scope.supportingEvidence.salesAddress.name,
					salesAddressComponents: $scope.supportingEvidence.salesAddressComponents
				},
				salesDate: $scope.supportingEvidence.salesDate,
				salesPrice: $scope.supportingEvidence.salesPrice,
				landArea: $scope.supportingEvidence.landArea,
				buildingArea: $scope.supportingEvidence.buildingArea,
				buildingCondition: $scope.supportingEvidence.buildingCondition,
				leaseAmt: $scope.supportingEvidence.leaseAmt,
				leaseTerm: $scope.supportingEvidence.leaseTerm,
				options: $scope.supportingEvidence.options,
				additionalInfo: $scope.supportingEvidence.additionalInfo,
				leaseTermYears: $scope.supportingEvidence.leaseTermYears,
				leaseTermMonths: $scope.supportingEvidence.leaseTermMonths
			});
			$scope.clearSuppotingEvidence($scope.supportingEvidence);
		};

		$scope.clearSuppotingEvidence = function () {
			$scope.supportingEvidence.salesAddress = {
				name: '',
				salesAddressComponents: {
					streetNumber: '',
					street: '',
					city: '',
					state: '',
					postCode: ''
				}
			};
			$scope.supportingEvidence.salesDate = null;
			$scope.supportingEvidence.salesPrice = '';
			$scope.supportingEvidence.landArea = '';
			$scope.supportingEvidence.buildingArea = '';
			$scope.supportingEvidence.buildingCondition = '';
			$scope.supportingEvidence.leaseAmt = '';
			$scope.supportingEvidence.leaseTerm = '';
			$scope.supportingEvidence.options = '';
			$scope.supportingEvidence.additionalInfo = '';
			$scope.supportingEvidence.leaseTermYears = '';
			$scope.supportingEvidence.leaseTermMonths = '';
		};

		$scope.deleteEvidence = function (evidence) {
			var index = $scope.model.supportingEvidences.indexOf(evidence);
			$scope.model.supportingEvidences.splice(index, 1);
		};

		/****************End Support Evedence***************/

		$scope.loadLookups = function () {
			return $http.get(window.location.origin + '/forms/WR/jsonData/lookups.json');
		};

		$scope.getFileDetails = function (e) {
			/*VN-597*/
			if ($scope.attachments === undefined) {
				$scope.attachments = [];
			}

			// STORE THE FILE OBJECT IN AN ARRAY.
			var isExist = false;
			$scope.attachmentsExceededMaxSize = false;
			for (var i = 0; i < e.files.length; i++) {
				for (var idx = 0; idx < $scope.attachments.length; idx++) {
					/*CHECK IF EXISTS, DONT ADD ATTACHMENTS*/
					if (e.files[i].name === $scope.attachments[idx].name) {
						isExist = true;
						break;
					}
				}

				if (!isExist) {
					e.files[i].uploadedSuccessful = false;
					$scope.$apply(function () {
						$scope.attachments.push(e.files[i]);
					});
				}

				if ($scope.attachments[idx].size >= $scope.AttachmentMaxSize) {
					$scope.attachmentsExceededMaxSize = true;
				}
			}

			$scope.uploadAttachments();
		};

		$scope.getAttachments = function () {
			objections.GetAttachments($scope.guid).then(function (result) {
				$scope.attachments = result.data.Data;
			});
		};

		$scope.uploadAttachments = function () {
			//upload file to aws s3
			$scope.hasUnsuccessfulAttachments = false;
			if ($scope.attachments.length > 0) {
				$scope.isUploading = true;
				objections.UploadFile($scope.attachments, $scope.guid).then(function (response) {
					$scope.isUploading = false;
					if (response.data.Data != null) {
						for (var i = 0; i < $scope.attachments.length; i++) {
							if ($scope.attachments[i].name === response.data.Data[i].FileName) {
								$scope.attachments[i].uploadedSuccessful = true;
							} else {
								$scope.hasUnsuccessfulAttachments = true;
							}
						}
						$scope.model.attachments = response.data.Data;
					}
				});
			}
		};

		$scope.removeAttachment = function (index) {
			var attachment = $scope.attachments[index];
			if (attachment) {
				attachment.deletingAttachment = true;
				objections.DeleteUploadedFile($scope.guid, attachment.name).then(function (response) {
					if (response.data.Code == 200) {
						$scope.attachments.splice(index, 1);
						$scope.model.attachments.splice(index, 1);
						$scope.attachmentsExceededMaxSize = false;
						$scope.hasUnsuccessfulAttachments = false;
						for (var i = 0; i < $scope.attachments.length; i++) {
							if ($scope.attachments[i].size > $scope.AttachmentMaxSize) {
								$scope.attachmentsExceededMaxSize = true;
							}
							if ($scope.attachments[i].uploadedSuccessful == false) {
								$scope.hasUnsuccessfulAttachments = true;
							}
						}

						$scope.uploadAttachments();
					}
					attachment.deletingAttachment = false;
				});
			}
		};

		$scope.bytesToFileSize = function (bytes, decimals) {
			if (bytes === 0) return '0 Bytes';

			if (decimals === 0)
				decimals = 2;

			const k = 1024;
			const dm = decimals < 0 ? 0 : decimals;
			const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
			const i = Math.floor(Math.log(bytes) / Math.log(k));

			return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
		};


		$scope.submitObjection = function () {
			$scope.model.valorClientId = $scope.clientId;
			$scope.model.valorBatchId = $scope.batchId;
			$scope.model.objectionFormType = $scope.objectionFormType;
			if ($scope.model.valuationDate) {
				$scope.model.valuationDate = moment($scope.model.valuationDate).format('YYYY-MM-DD');
			}

			$scope.ojection = {
				TitleJSON: JSON.stringify($scope.model.propertyAddress),
				FullJSON: JSON.stringify($scope.model),
				Type: $scope.objectionType,
				ReCaptchaToken: $scope.SubmitToken,
				GUID: $scope.guid,
				ObjectionFormType: $scope.objectionFormType
			};

			if ($scope.ojection.ReCaptchaToken === '') {
				$scope.showReCaptchaIsRequired = true;
			} else {
				$scope.showReCaptchaIsRequired = false;
			}

			$('.val-error-card').hide();
			if (!$scope.isValidForSubmission($scope.objectionForm)) {
				setTimeout(function () {
					var html = "<ul>";
					$('.has-error:visible').each(function () { html += "<li>" + $(this).text() + "</li>"; });

					if ($scope.isUploading) {
						html += "<li>Attachment is still processing.</li>";
					}

					html += "</ul>";
					$('.val-error-card').show('slow').find('.card-text').html(html);
					$('.val-error-card').find('#valTitle').html('Validation Error').parent('div').removeClass('bg-warning').addClass('bg-danger');
					$('html, body').animate({ scrollTop: $('.has-error:visible:first').offset().top - 100 }, 1000);
				}, 100);

				return;
			}

			if ($scope.ojection.ReCaptchaToken === '') {
				$scope.showReCaptchaIsRequired = true;
			} else {
				$scope.showSpinner = true;
				$scope.propertyDetailsLoading = true;
				$scope.showReCaptchaIsRequired = false;
				$scope.showValidationBox = false;
				objections.Submit($scope.ojection).then(function (objectionResult) {
					$scope.showSaveSpinner = false;
					$scope.propertyDetailsLoading = false;
					$scope.submitObjectionSuccessful = true;
					objections.EmailToObjector($scope.model, objectionResult.data.Id, false).then(function () { }, function (error) {
						$scope.error = "Objection submission succeeded but error occcur on the Objector Email.";
					});

					//valor integration is disabled
					if ($scope.batchId === '') {
						objections.EmailToCouncil($scope.model, objectionResult.data.Id, false).then(function () { }, function (error) {
							$scope.error = "Objection submission succeeded but error occcur on the Council Email.";
						});
					}
				}, function (err) {
					$scope.propertyDetailsLoading = false;
					$scope.showSpinner = false;
					$scope.showValidationBox = true;
					if (err.data === 'ReCaptcha') {
						$scope.error = "Invalid Captcha.";
					} else {
						$scope.error = "Objection submission failed. Please try again later or contact Administrator.";
					}
				});
			}
		};

		$scope.isValidModel = function () {
			return $scope.objectionForm.$valid;
		};

		$scope.oneContactRequired = function () {
			return !($scope.model.workPhone || $scope.model.homePhone || $scope.model.mobilePhone);
		};

		$scope.someObjectionGroundSelected = function (object) {
			return Object.keys(object).some(function (key) {
				return object[key];
			});
		};

		$scope.isValidForSubmission = function (form) {
			if (!$scope.oneContactRequired()
				&& $scope.someObjectionGroundSelected($scope.model.groundsForObjecting)
				&& $scope.model.fullName
				&& $scope.model.postalAddress.name
				&& $scope.model.email
				&& $scope.model.confirmEmail
				&& $scope.model.email == $scope.model.confirmEmail
				&& form.$valid
				&& !$scope.attachmentsExceededMaxSize
				&& $scope.model.supportingEvidences.length <= $scope.SupportingEvidenceMaxCount
				&& !$scope.hasUnsuccessfulAttachments
				&& !$scope.isUploading) {
				return true;
			}

			return false;
		};

		$scope.$watch('model', function (n, o) {
			//display validation while navigating	
			$scope.requiredOnSubmit = true;
		}, true);

		$scope.$watch('[model.propertyAddress.propertyAddressComponents,model.propertyAddress.dvrNumber]', function (n, o) {
			var searchBtn = angular.element(document.querySelector('#btnSearch'));
			if (angular.isDefined(n) || angular.isDefined(o)) {
				if (($scope.model.propertySearchType !== null && $scope.model.propertySearchType === $scope.PropertySearchTypeConstants.Address && angular.isDefined($scope.model.propertyAddress.propertyAddressComponents.streetNumber) && angular.isDefined($scope.model.propertyAddress.propertyAddressComponents.street) &&
					$scope.model.propertyAddress.propertyAddressComponents.streetNumber !== '' && $scope.model.propertyAddress.propertyAddressComponents.street !== '')
					|| ($scope.model.propertySearchType !== null && $scope.model.propertySearchType === $scope.PropertySearchTypeConstants.DVRNumber && $scope.model.propertyAddress.dvrNumber !== '' && angular.isDefined($scope.model.propertyAddress.dvrNumber))) {
					searchBtn.attr('disabled', false);
				} else {
					searchBtn.attr('disabled', true);
				}
			}
		}, true);

		$scope.showSimpleToast = function (message) {
			var pinTo = $scope.getToastPosition();
			$mdToast.show(
				$mdToast.simple()
					.textContent(message)
					.position(pinTo)
					.hideDelay(3000)
					.toastClass('toast-save')
			);
		};

		$scope.showListOfValorProperty = function () {
			$mdDialog.show({
				locals: { model: $scope.model },
				controller: DialogController,
				templateUrl: '/Forms/Shared/html/dialog.html?v=' + $scope.version, //parameter v, to force refresh template
				parent: angular.element(document.body),
				clickOutsideToClose: false
			});
		};

		$rootScope.closeDialog = function () {
			$mdDialog.cancel();
		};

		$scope.manualPropertyDetails = function () {
			if ($scope.model.propertyAddress.manualEntry === true) {
				$scope.manualAddress();

				$scope.model.propertySearchType = $scope.PropertySearchTypeConstants.Address;
			} else {
				$scope.model.propertyAddress.name = '';
				$scope.model.propertyAddress.propertyAddressComponents.unitNumber = '';
				$scope.model.propertyAddress.propertyAddressComponents.streetNumber = '';
				$scope.model.propertyAddress.propertyAddressComponents.street = '';
				$scope.model.propertyAddress.propertyAddressComponents.postCode = '';
				$scope.model.propertyAddress.propertyAddressComponents.suburb = '';

				$scope.model.dvrNumber = '';
				$scope.model.councilPropertyId = '';
				$scope.model.titleNumber = '';
				$scope.model.legalDescription = '';
			}
		};

		$scope.concatAddress = function () {
			if ($scope.model.propertyAddress.manualEntry) {
				$scope.manualAddress();
			}
		};

		$scope.manualAddress = function () {
			var unitNumber = $scope.model.propertyAddress.propertyAddressComponents.unitNumber;
			var streetNumber = $scope.model.propertyAddress.propertyAddressComponents.streetNumber;
			var street = $scope.model.propertyAddress.propertyAddressComponents.street;
			var postCode = $scope.model.propertyAddress.propertyAddressComponents.postCode;
			var suburb = $scope.model.propertyAddress.propertyAddressComponents.suburb;
			var array = new Array(streetNumber, street, postCode, suburb);
			var filtered = array.filter(function (el) {

				if (el != null && el != '') {
					return true;
				}
				return false;
			});

			if (unitNumber != null && unitNumber != '') {
				$scope.model.propertyAddress.name = unitNumber + '/' + filtered.join(', ');
			} else {
				$scope.model.propertyAddress.name = filtered.join(', ');
			}
		};

		$scope.resetSearchProperty = function () {
			$scope.model.propertyAddress.name = '';
			$scope.model.legalDescription = '';
			$scope.model.titleNumber = '';
			$scope.model.dvrNumber = '';//valuationReferenceNumber = '';
			$scope.model.councilPropertyId = '';
			$scope.model.landValueCouncil = '';
			$scope.model.improvementsCouncil = '';
			$scope.model.capitalCouncil = '';

			if ($scope.model.propertySearchType == $scope.PropertySearchTypeConstants.Address) {
				$scope.model.propertyAddress.dvrNumber = '';
			}
			else if ($scope.model.propertySearchType == $scope.PropertySearchTypeConstants.TitleNumber) {
				$scope.model.propertyAddress.titleNumber = '';
			}
			else {
				$scope.model.propertyAddress.propertyAddressComponents.unitNumber = '';
				$scope.model.propertyAddress.propertyAddressComponents.streetNumber = '';
				$scope.model.propertyAddress.propertyAddressComponents.street = '';
				$scope.model.propertyAddress.propertyAddressComponents.postCode = '';
				$scope.model.propertyAddress.propertyAddressComponents.suburb = '';
				$scope.model.propertyAddress.manualEntry = false;
			}
		};

		$scope.loadCaptcha = function () {
			grecaptcha.render('btnSearch', {
				'sitekey': objectionConfig.googleSiteKey,
				'callback': 'searchPropertyInValor',
				'size': 'invisible'
			});

			grecaptcha.render('btnSubmit', {
				'sitekey': objectionConfig.googleSiteKey,
				'callback': 'onSecondCaptchaValidation'
			});

			//init set button disabled
			angular.element(document.querySelector('#btnSearch')).attr('disabled', true);
		};

		$scope.onSecondCaptchaValidation = function (token) {
			$scope.SubmitToken = token;
		};

		$scope.searchPropertyInValor = function (token) {
			$scope.propertyDetailsLoading = true;
			var searchValue = null;
			var searchType = $scope.model.propertySearchType;
			if ($scope.model.propertySearchType == $scope.PropertySearchTypeConstants.Address) {
				var street = 0;
				if (!hasNumber($scope.model.propertyAddress.propertyAddressComponents.streetNumber)) {
					street = $scope.model.propertyAddress.propertyAddressComponents.streetNumber.replace(/\D/g, '');
				}

				searchValue = street + ',' + $scope.model.propertyAddress.propertyAddressComponents.street;
			} else if ($scope.model.propertySearchType == $scope.PropertySearchTypeConstants.DVRNumber) {
				searchValue = $scope.model.propertyAddress.dvrNumber;
			} else if ($scope.model.propertySearchType == $scope.PropertySearchTypeConstants.TitleNumber) {
				searchValue = $scope.model.propertyAddress.titleNumber;
			}

			objections.SearchValorProperty(searchValue, searchType, $scope.clientId, token).then(function (response) {
				$scope.propertyDetailsLoading = false;
				$rootScope.properties = [];
				let _data = [];
				if ($scope.objectionFormType == _revalJobTypeConst) {
					// if reval
					_data = response.data.filter(function (item) { return item.JobTypeId == $scope.objectionFormType && item.JobStatusId == _closeJobStatusConst && item.IsSupplementaryMaintenanceYear; });
				} else {
					// if supp
					// ticket 67458, we'll show all closed jobs regardless of jobtype
					_data = response.data.filter(function (item) { return item.JobStatusId == _closeJobStatusConst });
				}

				$rootScope.properties = _data.map(d => ({
					titleNumber: LimitTitleAndLegalDescriptionList(d.TitleNumberList),
					dvrNumber: d.DVRNumber,
					legalDescription: LimitTitleAndLegalDescriptionList(d.LegalDescriptionList),
					address: d.Address,
					propertyId: d.PropertyId,
					referenceNo: GenerateValuationReferenceNumber(d.RollNumber, d.ValuationNumber, d.Suffix),
					councilReferenceNumber: d.CouncilReference,
					currentCIV: $scope.objectionFormType == _revalJobTypeConst ? d.CurrentCIV : (d.JobTypeId == _revalJobTypeConst ? 0 : d.CurrentCIVSuppJob),
					currentIV: $scope.objectionFormType == _revalJobTypeConst ? d.CurrentIV : (d.JobTypeId == _revalJobTypeConst ? 0 : d.CurrentIVSuppJob),
					currentLV: $scope.objectionFormType == _revalJobTypeConst ? d.CurrentLV : (d.JobTypeId == _revalJobTypeConst ? 0 : d.CurrentLVSuppJob),
					jobClosedDate: d.JobClosedDateSuppJob == null ? '' : d.JobClosedDateSuppJob,
					age: d.JobClosedDateSuppJob == null ? 0 : moment().diff(moment(d.JobClosedDateSuppJob).format('YYYY-MM-DD'), 'days')
				}));

				if ($rootScope.properties.length > 1) {
					$rootScope.properties = $rootScope.properties.slice(0, 25);
					$scope.showListOfValorProperty();
					$scope.showManualPropertyEntry = false;
				} else if ($rootScope.properties.length === 1) {
					checkSuppJobAgeLimit($rootScope.properties[0]);
					propertyDetail($rootScope.properties[0]);
					$scope.showManualPropertyEntry = false;
				} else {
					$scope.resetSearchProperty();
					$scope.showManualPropertyEntry = true;

					Swal.fire({
						position: "center",
						icon: "info",
						html: "<label>No Records Found</label>",
						timer: 3000,
						showConfirmButton: false,
						showCancelButton: true,
						cancelButtonText: '<i class="fa fa-times"></i> Close',
						cancelButtonAriaLabel: "Close"
					});
				}
			}, function (error) {
				$scope.showManualPropertyEntry = true;
				$scope.propertyDetailsLoading = false;
				$scope.model.propertyAddress.name = '';
			});

			grecaptcha.reset();
		};

		//data-callback for google captcha expect a global function to work
		//creating $window function that inherit $scope function resolve the issue
		$window.loadCaptcha = $scope.loadCaptcha;
		$window.onSecondCaptchaValidation = $scope.onSecondCaptchaValidation;
		$window.searchPropertyInValor = $scope.searchPropertyInValor;


		$scope.haveValorProperties = function () {
			if ($rootScope.properties.length > 0) {
				return true;
			}
			return false;
		};

		$scope.calculateImprovementsEstimated = function () {
			$scope.model.improvementsEstimated = $scope.model.capitalEstimated - $scope.model.landValueEstimated;
		};

		$rootScope.$on('PropertyDetail', function (event, obj) {
			propertyDetail(obj.prop);
		});

		$scope.addSupportingEvidence = function () {
			$scope.setFocus = true;
			$scope.clearSuppotingEvidence();
			$scope.showFormSupEvidence = true;
		};

		$scope.cancelSupportingEvidence = function () {
			$scope.clearSuppotingEvidence();
			$scope.showFormSupEvidence = false;
		};

		$scope.editSupportingEvidence = function (supEvidence) {
			$scope.setFocus = true;
			$scope.supportingEvidence = JSON.parse(JSON.stringify(supEvidence));
			$scope.showFormSupEvidence = true;
		};

		$scope.saveSupportingEvidence = function () {
			if ($('#form-sup-evidence').find('.ng-invalid').length > 0) {
				$('#form-sup-evidence').find('.ng-invalid:first').focus();
				return;
			}

			var supEvidence = JSON.parse(JSON.stringify($scope.supportingEvidence));
			if (supEvidence && supEvidence.$$hashKey) {
				var foundIndex = $rootScope.model.supportingEvidences.findIndex(function (item) { return item.$$hashKey == supEvidence.$$hashKey; });
				$rootScope.model.supportingEvidences.splice(foundIndex, 1, supEvidence);
			} else {
				$rootScope.model.supportingEvidences.push(supEvidence);
			}

			$scope.supportingEvidence.$$hashKey = '';
			$scope.showFormSupEvidence = false;
		};

		$scope.resetModel = function () {
			window.location.href = '/';
		};

		$scope.setModel = function (objection) {
			if (objection.FullJSON === '') {
				$scope.lastSavedJSON = JSON.stringify($scope.model); // stringify empty model and set as lastSavedJSON
				$scope.model.lastSaved = new Date();
			}
			else {
				$scope.lastSavedJSON = objection.FullJSON;
				$scope.model = angular.fromJson(objection.FullJSON);
			}
		};

		$scope.loadObjection = function () {
			return objections.Get($scope.objectionId);
		};

		$scope.resendToObjector = function () {
			$scope.propertyDetailsLoading = true;
			objections.EmailToObjector($scope.model, $scope.objectionId, true).then(function () {
				$scope.propertyDetailsLoading = false;
			}, function (error) {
				$scope.error = "Objection submission succeeded but error occcur on the Council Email.";
				$scope.propertyDetailsLoading = false;
			});
		}

		$scope.resendToCouncil = function () {
			$scope.propertyDetailsLoading = true;
			objections.EmailToCouncil($scope.model, $scope.objectionId, true).then(function () {
				$scope.propertyDetailsLoading = false;
			}, function (error) {
				$scope.error = "Objection submission succeeded but error occcur on the Council Email.";
				$scope.propertyDetailsLoading = false;
			});
		}

		$scope.queueValorIntegration = function () {
			$scope.propertyDetailsLoading = true;
			objections.QueueValorIntegration($scope.model, $scope.objectionId).then(function (result) {
				if (result.data.Code === 500) {//internal error
					$scope.showValidationBox = true;
					$scope.error = result.data.Message;
					$scope.propertyDetailsLoading = false;
				} else {
					$scope.showValidationBox = false;
					$scope.propertyDetailsLoading = false;
				}
			});
		}

		$scope.displayPropertyValues = function () {
			if ($scope.model.groundsForObjecting.propertyValue == true || $scope.model.groundsForObjecting.improvements == true) {
				return true;
			} else {
				return false;
			}
		};

		$scope.ValuationShowHide = function (object) {
			var ShowHide = false;
			return Object.keys(object).some(function (key) {
				if ((object['propertyValue'] && !object['improvements'] && !object['noticeOfValuation']) || (object['improvements'] || !object['areaOrDescription']) || (object['improvements']))
					ShowHide = true;
				else if (object['noticeOfValuation'] || object['areaOrDescription'] || object['improvements'])
					ShowHide = false;
				return ShowHide;
			});
		};

		$scope.ShowHide = function (object) {
			var ShowHide = false;
			return Object.keys(object).some(function (key) {
				if ((object['noticeOfValuation']) && (!object['areaOrDescription'] && !object['improvements'] && !object['other'])) {
					ShowHide = false;
				}
				else if (object['propertyValue'] || object['improvements'] || object['areaOrDescription'] || object['other']) {
					ShowHide = true;
				}
				return ShowHide;
			});
		};
		$scope.displayAttachments = function () {
			return $scope.model.groundsForObjecting.noticeOfValuation == true;
		};
		function propertyDetail(property) {
			$scope.model.landArea = property.landArea;
			$scope.model.titleNumber = property.titleNumber;
			$scope.model.legalDescription = property.legalDescription;
			$scope.model.dvrNumber = property.dvrNumber;
			$scope.model.councilPropertyId = property.councilReferenceNumber;
			$scope.model.propertyAddress.name = property.address;
			$scope.model.valuationReferenceNumber = property.councilReferenceNumber;
			$scope.model.landValueCouncil = property.currentLV;
			$scope.model.improvementsCouncil = property.currentIV;
			$scope.model.capitalCouncil = property.currentCIV;
		}

		function DialogController($scope, $mdDialog) {
			$scope.hide = function () {
				$mdDialog.hide();
			};

			$scope.cancel = function () {
				$mdDialog.cancel();
			};

			$scope.getDetails = function (prop) {
				checkSuppJobAgeLimit(prop);

				$rootScope.$broadcast('PropertyDetail', { prop: prop });
				$scope.hide();
			};
		}

		function checkSuppJobAgeLimit(prop) {
			//check if objection form is maintenance
			//JobStatusHistory record Createddate/Closeddate > the cutoff day
			//jobClosedDate = null means no supp job for the assessment
			if ($scope.objectionFormType != _revalJobTypeConst && (prop.jobClosedDate == '' || prop.age > $scope.suppNoJobsNoDays)) {
				// show the message
				var modalBody = $('.val-error-card').show('slow').find('.card-text');
				modalBody.html(modalBody.html().replace(/{valuationReference}/gi, prop.dvrNumber).replace(/{valuationAddress}/gi, prop.address));

				$('.val-error-card').find('#valTitle').html('Supp Job Notification').parent('div').removeClass('bg-danger').addClass('bg-warning');

				// clear the values
				prop.currentCIV = 0;
				prop.currentIV = 0;
				prop.currentLV = 0;

				// flag if maintenance/supp job is non-supp
				$scope.model.nonSupplementary = true;
			}
		}

		function GenerateValuationReferenceNumber(rollNumber, valuationNumber, suffix) {
			if (rollNumber === null || valuationNumber === null || !angular.isDefined(valuationNumber) || !angular.isDefined(rollNumber)) {
				return '';
			}
			if (!angular.isDefined(suffix) || suffix === null) {
				suffix = '';
			}

			return rollNumber + valuationNumber + suffix;
		}

		function hasNumber(myString) {
			return /^[A-Za-z]+$/.test(myString);
		}

		function LimitTitleAndLegalDescriptionList(list) {
			if (list.length <= 0) {
				return '';
			} else if (list.length === 1) {
				return list.toString();
			}

			const len = 83;
			var stringList = list.join(', ');

			if (stringList.length < len) {
				return stringList;
			}

			var res = stringList.substring(0, len);

			return res + '...& Others';
		}

	}]);

app.directive('ngFocus', function ($timeout) {
	return {
		link: function (scope, element, attrs) {
			scope.$watch(attrs.ngFocus, function (val) {
				if (angular.isDefined(val) && val) {
					$timeout(function () { element[0].focus(); });
				}
			}, true);

			element.bind('blur', function () {
				if (angular.isDefined(attrs.ngFocusLost)) {
					scope.$apply(attrs.ngFocusLost);

				}
			});
		}
	};
});

app.filter('DateFormat', function () {
	return function (inputDate) {
		var dateFormat = "DD/MM/YYYY";
		var date = moment(inputDate);
		if (date.isValid())
			return date.format(dateFormat);
		else
			return '';
	};
});

app.directive('validDate', function () {
	return {
		require: 'ngModel',
		link: function (scope, element, attributes, control) {
			control.$validators.validDate = function (modelValue) {

				if (control.$isEmpty(modelValue))
					return true;

				var dateFormat = "DD/MM/YYYY";
				var date = moment(modelValue, dateFormat, true);
				if (date.isValid())
					return true;
				else
					return false;
			};
		}
	};
});

app.directive('focusMe', function ($timeout, $parse) {
	return {
		link: function (scope, element, attrs) {
			var model = $parse(attrs.focusMe);
			scope.$watch(model, function (value) {
				if (value === true) {
					$timeout(function () {
						element[0].focus();
					});
				}
			});
			element.bind('blur', function () {
				scope.$apply(model.assign(scope, false));
			});
		}
	};
});

app.directive('alphaNumericValidation', function () {
	return {
		require: 'ngModel',
		restrict: 'A',
		link: function (scope, element, attributes, control) {

			control.$validators.alphaNumericValidation = function (modelValue) {
				if (/^[a-zA-Z0-9\s]*$/.test(modelValue)) {
					return true;
				} else {
					return false;
				}
			};
		}
	};
});

app.directive('phoneNumberValidation', function () {
	return {
		require: 'ngModel',
		restrict: 'A',
		link: function (scope, element, attributes, control) {

			control.$validators.phoneNumberValidation = function (modelValue) {
				if (/^[0-9- ]*$/.test(modelValue)) {
					return true;
				} else {
					return false;
				}
			};
		}
	};
});

app.directive('numberOnly', function () {
	return {
		restrict: 'A',
		require: 'ngModel',
		link: function (scope, element, attrs, modelCtrl) {
			modelCtrl.$parsers.push(function (inputValue) {
				if (inputValue == undefined) return '';
				var transformedInput = inputValue.replace(/[^0-9 ]/g, '');
				if (transformedInput !== inputValue) {
					modelCtrl.$setViewValue(transformedInput);
					modelCtrl.$render();
				}
				return transformedInput;
			});
		}
	};

});


app.directive('fileModel', ['$parse', function ($parse) {
	return {
		restrict: 'A'
		, link: function (scope, element, attrs) {
			var model = $parse(attrs.fileModel);
			var modelSetter = model.assign;
			element.bind('change', function () {
				var files = [];
				angular.forEach(element[0].files, function (file) {
					files.push(file);
				});
				scope.$apply(function () {
					modelSetter(scope, files);
				});
			});
		}
	};
}]);

app.config(function ($mdDateLocaleProvider) {
	$mdDateLocaleProvider.formatDate = function (date) {
		var m = moment(date);
		return m.isValid() ? m.format('DD/MM/YYYY') : '';
	};

	$mdDateLocaleProvider.parseDate = function (date) {
		var m = moment(date, 'DD/MM/YYYY', true);
		return m.isValid() ? m.toDate() : new Date(NaN);
	};
});
(function () {
	var module = angular.module('app');
	module.factory('Objection', ['$http', function ($http) {
		var StatusEnum = {
			"1": "Draft",
			"5": "Submitted",
			"10": "Withdrawn",
			"15": "Deleted"
		};

		function deserializeList(data) {
			var o = JSON.parse(data);
			for (var i = 0; i < o.Items.length; i++) {
				normaliseAfterDeserialisation(o.Items[i]);
			}
			return o;
		}
		var msTimezoneOffset = new Date().getTimezoneOffset() * -1 * 60000; //the offset value is -600 for +10, so multiply by -1 to normalize. 60000 = number of ms in a minute
		function deserialize(data) {
			var o = JSON.parse(data);
			normaliseAfterDeserialisation(o);
			return o;
		}
		function normaliseAfterDeserialisation(o) { //We use the built-in parser, but need to normalise date and enum field types
			if (o.CreatedAt) {
				o.CreatedAt = new Date(parseInt(o.CreatedAt) - msTimezoneOffset); //Normalise the incoming value back to UTC as [new Date()] expects
			}
			if (o.UpdatedAt) {
				o.UpdatedAt = new Date(parseInt(o.UpdatedAt) - msTimezoneOffset); //Normalise the incoming value back to UTC as [new Date()] expects
			}
		}
		var validFields = {
			"ID": true,
			"TitleJSON": true,
			"FullJSON": true,
			"Status": true,
			"CreatedAt": true,
			"UpdatedAt": true,
			"VersionNumber": true,
			"User": true,
			"ReCaptchaToken": true,
			"GUID": true,
			"ObjectionFormType": true
		};
		function includeField(name, o) //For entity Patch patterns, only changed fields should be included in the JSON model
		{
			if ((name in o) === false)
				return false;

			if (name in validFields === false)
				return false;
			//We have our own convention, to track a {o}.$meta.changed.{fieldName} boolean in our viewModel
			if (('$meta' in o) === false)
				return true; //nothing more to consider

			var meta = o['$meta'];

			var hasChangedTracking = ('changed' in meta);
			var hasMaximumFieldsDefinition = ('affectedFields' in meta);

			return ((hasChangedTracking && meta.changed[name]) || !hasChangedTracking) &&
				((hasMaximumFieldsDefinition && meta.affectedFields[name]) || !hasMaximumFieldsDefinition)
		}
		function serialize(o) {   //We just make a copy that has only the fields needed/supported and that have changed
			var cleanModel = {};
			for (var property in o) {
				if (includeField(property, o)) {
					cleanModel[property] = o[property]; //COPY
				}
			}

			if (cleanModel.CreatedAt instanceof Date) {
				cleanModel.CreatedAt = cleanModel.CreatedAt.valueOf() + msTimezoneOffset; //Store the JS Date as ms since 1970 (LocalTime)
			}
			if (cleanModel.UpdatedAt instanceof Date) {
				cleanModel.UpdatedAt = cleanModel.UpdatedAt.valueOf() + msTimezoneOffset; //Store the JS Date as ms since 1970 (LocalTime)
			}
			if (cleanModel.User) {
				cleanModel.User = { ID: cleanModel.User.ID };
			}
			return JSON.stringify(cleanModel); //Use the standard serializer
		}
		return {
			Get: function (ID) {
				return $http({ method: 'GET', url: '/api/Cubetec/Objections/Get', params: { ID: ID }, transformResponse: deserialize });
			},
			Submit: function (item) {
				return $http({ method: 'POST', url: '/noauth/cubetec/objection/submit', data: item, transformRequest: serialize, transformResponse: deserialize });
			},
			EmailToCouncil: function (model, objectionId, resend) {
				model.objectionId = objectionId;
				return $http({
					method: 'POST',
					params: { resend: resend },
					url: '/noauth/tocouncil',
					dataType: 'json',
					data: model,
					headers: {
						"Content-Type": "application/json"
					}
				});
			},
			EmailToObjector: function (model, objectionId, resend) {
				model.objectionId = objectionId;
				return $http({
					method: 'POST',
					params: { resend: resend },
					url: '/noauth/toobjector',
					dataType: 'json',
					data: model,
					headers: {
						"Content-Type": "application/json"
					}
				});
			},
			GenerateObjectionPDF: function (model) {
				return $http({
					method: 'POST',
					url: "/noauth/pdf",
					dataType: 'json',
					data: model,
					headers: {
						"Content-Type": "application/json"
					}
				});
			},
			UploadFile: function (files, guid) {
				var fd = new FormData();
				for (let i = 0; i < files.length; i++) {
					fd.append("file" + i, files[i]);
				}
				return $http({
					method: 'POST', url: '/noauth/file/upload'
					, params: { guid: guid }
					, transformRequest: angular.identity
					, data: fd
					, headers: { 'Content-Type': undefined }
				});
			},
			SearchValorProperty: function (search, searchType, clientId, token) {
				return $http({ method: 'POST', url: '/noauth/cubetec/objection/valor/getproperty', params: { search: search, searchType: searchType, clientId: clientId, token: token }, transformResponse: deserialize }).then(function (response) {
					return response;
				});
			},
			GetAttachments: function (guid) {
				return $http({ method: 'GET', url: '/noauth/file/getattachments', params: { guid: guid }, transformResponse: deserialize });
			},
			QueueValorIntegration: function (model, objectionId) {
				return $http({
					method: 'POST',
					url: '/noauth/queue/valorintegration',
					params: { objectionId: objectionId },
					dataType: 'json',
					data: model,
					headers: {
						"Content-Type": "application/json"
					}
				});
			},
			DeleteUploadedFile: function (guid, fileName) {
				return $http({
					method: 'POST',
					url: '/noauth/file/upload/delete',
					params: { guid: guid, fileName: fileName },
					dataType: 'json',
					headers: {
						"Content-Type": "application/json"
					}
				});
			}
		};
	}]);
	module.constant('ObjectionConfig', {
		googleSiteKey: '6LfH0_4UAAAAAOXGEufn4U8CcOrzzP8vlzCXfWyq'
	});
})();

