var periodInputController = function(utilsFactory, $scope, $timeout) {
	var ctrl = this;

	var timestamp = new Date().getTime()
	ctrl.inputId = "period-input-" + timestamp;

	ctrl.months = [
		{ id: "1", label: "Gennaio" },
		{ id: "2", label: "Febbraio" },
		{ id: "3", label: "Marzo" },
		{ id: "4", label: "Aprile" },
		{ id: "5", label: "Maggio" },
		{ id: "6", label: "Giugno" },
		{ id: "7", label: "Luglio" },
		{ id: "8", label: "Agosto" },
		{ id: "9", label: "Settembre" },
		{ id: "10", label: "Ottobre" },
		{ id: "11", label: "Novembre" },
		{ id: "12", label: "Dicembre" }
	]
	ctrl.monthParseReplacements = {
		"gennaio": "1",
		"febbraio": "2",
		"marzo": "3",
		"aprile": "4",
		"maggio": "5",
		"giugno": "6",
		"luglio": "7",
		"agosto": "8",
		"settembre": "9",
		"ottobre": "10",
		"novembre": "11",
		"dicembre": "12",
		"january": "1",
		"february": "2",
		"march": "3",
		"april": "4",
		"may": "5",
		"june": "6",
		"july": "7",
		"august": "8",
		"september": "9",
		"october": "10",
		"november": "11",
		"december": "12",
		"jan.": "1",
		"feb.": "2",
		"mar.": "3",
		"apr.": "4",
		"jun.": "6",
		"jul.": "7",
		"aug.": "8",
		"sep.": "9",
		"oct.": "10",
		"nov.": "11",
		"dec.": "12"
	}

	var currentYear = new Date().getFullYear()
	var yearsToGenerate = 10;

	ctrl.years = [];
	for(var i = 0; i < yearsToGenerate; i++) {
		var year = (currentYear - i).toString();
		ctrl.years.push({ id: year, label: year });
	}

	if(ctrl.allowEmpty) {
		ctrl.months.splice(0, 0, { id: null, label: "Mese" })
		ctrl.years.splice(0, 0, { id: null, label: "Anno" })
	}

	ctrl.minDate = new Date((currentYear - yearsToGenerate).toString() + "-01-01")
	ctrl.maxDate = new Date()

	ctrl.modelInternal = null
	ctrl.mode = "FULL"
	ctrl.form = {
		periodEntries: [],
		date: null,
		day: null,
		month: null,
		year: null
	}

	ctrl.$onInit = function() {
		ctrl.modelInternal = ctrl.model

		ctrl.checkValidation()

		var today = new Date()

		if(ctrl.allowEmpty !== true && utilsFactory.isNullOrUndefined(ctrl.model)) {
			ctrl.initFormWithDate("FULL", today)
		}

		if(utilsFactory.isBlank(ctrl.model)) {
			ctrl.onChange()
			return
		}

		var value = extractDate(ctrl.model)
		if(/^\d{4}$/.test(value)) {
			ctrl.initForm("YEAR", "01", "01", value.toString())
			return
		}

		var splitted = value.split("-")
		if(splitted.length === 1) {
			if(/^\d{4}$/.test(value)) {
				ctrl.initForm("YEAR", "01", "01", value.toString())
				return
			}

			if(ctrl.allowEmpty === true) {
				ctrl.modelInternal = ""
				ctrl.onChange()
			} else {
				ctrl.initFormWithDate("FULL", today)
			}
			return;
		}
		if(splitted.length === 2) {
			// accepts mm-yyyy and yyyy-mm (0-padding on month is optional)
			if(!/^(?:(?:0?[1-9]|1[0-2])-\d{4}|\d{4}-(?:0?[1-9]|1[0-2]))$/.test(value)) {
				if(ctrl.allowEmpty === true) {
					ctrl.modelInternal = ""
					ctrl.onChange()
				} else {
					ctrl.initFormWithDate("FULL", today)
				}
				return  // use default
			}

			if(splitted[0].length === 4) {
				ctrl.initForm("MONTH_YEAR", "01", splitted[1], splitted[0])
			} else {
				ctrl.initForm("MONTH_YEAR", "01", splitted[0], splitted[1])
			}
			return
		}

		// accepts dd-mm-yyyy and yyyy-mm-dd (0-padding on month and day is optional)
		if(!/^(?:(?:0?[1-9]|[1-2]\d|3[0-1])-(?:0?[1-9]|1[0-2])-\d{4}|\d{4}-(?:0?[1-9]|1[0-2])-(?:0?[1-9]|[1-2]\d|3[0-1]))$/.test(value)) {
			if(ctrl.allowEmpty === true) {
				ctrl.modelInternal = ""
				ctrl.onChange()
			} else {
				ctrl.initFormWithDate("FULL", today)
			}
			return  // use default
		}
		if(splitted[0].length === 4) {
			ctrl.initForm("FULL", splitted[2], splitted[1], splitted[0])
		} else {
			ctrl.initForm("FULL", splitted[0], splitted[1], splitted[2])
		}
	}

	var extractDate = function(value) {
		var v = value
			.replaceAll(/[\/.]/g, "-")
			.replaceAll(/\s*/g, "")
			.trim()

		var r = /((?:(?:0?[1-9]|[1-2]\d|3[0-1])-)?(?:0?[1-9]|1[0-2])-\d{4}|\d{4}-(?:0?[1-9]|1[0-2])(?:-(?:0?[1-9]|[1-2]\d|3[0-1]))?)/
		var matches = v.match(r)
		if(matches !== null && matches.length >= 2) {
			return matches[1]
		}

		return tryParseDateWithWords(value.trim())
	}

	var tryParseDateWithWords = function(value) {
		var r = /(?:0?([1-9]|[1-2]\d|3[0-1])\s)?([a-z.]{3,})\s(\d{4})/i
		var matches = value.match(r)

		if(matches != null && matches.length >= 3) {
			return joinParsedDate(matches[1], matches[2], matches[3])
		}

		var rEnglish = /(([a-z.]{3,}\s)?(?:0?([1-9]|[1-2]\d|3[0-1])(?:st|nd|rd|th)?\s)?(\d{4}))/i
		matches = value.match(rEnglish)
		if(matches != null && matches.length === 5) {
			return joinParsedDate(matches[3], matches[2], matches[4])
		}

		return value
	}

	var joinParsedDate = function(day, month, year) {
		var dateArray = []
		var m = replaceMonths(month)
		var isMonthValid = utilsFactory.isNotBlank(m) && !isNaN(parseInt(m))

		if(utilsFactory.isNotBlank(day) && isMonthValid) {
			dateArray.push(day)
		}
		if(isMonthValid) {
			dateArray.push(m)
		}
		dateArray.push(year)
		return dateArray.join("-")
	}

	var replaceMonths = function(value) {
		var result = (value || "").toLowerCase().trim()
		Object.entries(ctrl.monthParseReplacements)
			.forEach(function(entry) {
				var found = result.indexOf(entry[0]) >= 0
				result = result.replace(entry[0], entry[1])
				return !found
			})

		return result
	}

	ctrl.$onChanges = function() {
		if(ctrl.modelInternal === ctrl.model) {
			return
		}

		ctrl.$onInit()
	}

	ctrl.initFormWithDate = function(mode, date) {
		if(utilsFactory.isNullOrUndefined(date)) {
			ctrl.initForm(mode, null, null, null);
			return
		}

		ctrl.initForm(
			mode,
			date.getDate().toString(),
			(date.getMonth() + 1).toString(),
			date.getFullYear().toString()
		)
	}

	ctrl.initForm = function(mode, day, month, year) {
		ctrl.mode = mode

		var monthToSearch = null
		if(utilsFactory.isNotNullAndNotUndefined(month)) {
			monthToSearch = month.replace("0", "")
		}
		var theMonth = ctrl.months
			.find(function(it ) { return it.id === monthToSearch })

		var theYear = ctrl.years
			.find(function(it ) { return it.id === year })

		day = day || "1"
		ctrl.form = {
			day: day,
			month: theMonth,
			year: theYear
		}

		ctrl.form.periodEntries = []
		if(utilsFactory.isNullOrUndefined(month) ||
			utilsFactory.isNullOrUndefined(year)) {
			return
		}

		ctrl.form.date = new Date(year + "-" + month + "-" + day)

		if(mode === "YEAR") {
			ctrl.form.periodEntries.push(year)
			ctrl.modelInternal = year
		} else if(mode === "MONTH_YEAR") {
			ctrl.form.periodEntries.push(theMonth.label, year)
			ctrl.modelInternal = month.padStart(2, "0") + "/" + year
		} else {
			ctrl.form.periodEntries.push(day.padStart(2, "0"), theMonth.label, year)
			ctrl.modelInternal = day.padStart(2, "0") + "/" + month.padStart(2, "0") + "/" + year
		}

		if(ctrl.model !== ctrl.modelInternal) {
			ctrl.onChange()
		}
	}

	ctrl.checkValidation = function() {
		if(utilsFactory.isNotNullAndNotUndefined(ctrl.validation)) {
			return
		}
		ctrl.validation = {
			validate: function() {
				ctrl.validation.status = "NO_ERROR";
			},
			status: "NO_ERROR",
			errors: {
				"NO_ERROR": "Ok"
			}
		}
	};

	ctrl.onChange = function() {
		ctrl.validation.validate(ctrl.modelInternal)

		if(!ctrl.onInputChange) {
			return;
		}
		ctrl.onInputChange({ value: ctrl.modelInternal })
	}

	ctrl.changeMode = function(mode) {
		utilsFactory.safeApply($scope, function() {
			var month = null, year = null
			if(utilsFactory.isNotNullAndNotUndefined(ctrl.form.month)) {
				month = ctrl.form.month.id
			}
			if(utilsFactory.isNotNullAndNotUndefined(ctrl.form.year)) {
				year = ctrl.form.year.id
			}
			ctrl.initForm(mode, ctrl.form.day, month, year)
			ctrl.onChange()
		})
	}

	ctrl.periodChanged = function() {
		ctrl.changeMode(ctrl.mode)
	}

	ctrl.dateChanged = function() {
		utilsFactory.safeApply($scope, function() {
			ctrl.initFormWithDate(ctrl.mode, ctrl.form.date)
			ctrl.onChange()
		})
	}

	ctrl.onEditClick = function() {
		$timeout(function() {
			$("#" + ctrl.inputId).click()
		})
	}

	ctrl.onClearClick = function() {
		ctrl.form = {
			date: null,
			day: null,
			month: null,
			year: null
		}

		ctrl.form.periodEntries = []
		ctrl.modelInternal = null

		ctrl.onChange()
	}
}

angular.module('sinossi.components').component('periodInputComponent', {
	templateUrl: 'scripts/components/periodInputComponent/views/periodInputTemplate.html',
	controller: periodInputController,
	bindings: {
		label: "@",
		mandatory: "<?",
		disableFlag: "<?",
		model: "<",
		onInputChange: "&?",
		allowEmpty: "<?",
		validation: "<?"
	}
});