angular.module("app").directive("datePicker", function ($rootScope, $timeout, UniqueIdGenerator, L) {
    return {
        restrict: 'E',
        replace: true,
        templateUrl: "../app/directives/datePicker/datePicker.html",
        scope: {
            label: '@',
            format: '@',
            date: '=',
            minDate: '=',
            maxDate: '=',
            onDateChange: '&',
            ngDisabled: '=',
            forceDateChange: '=',
            sqclass: "@",
        },
        link: function (scope, element, attrs) {

            scope.onDateChanged = function (newValue) {
                //console.error("onDateChanged", lastDateTime, newValue);
                if (lastDateTime == newValue) {
                    return;
                }

                lastDateTime = newValue;

                var correctedDate = correctDate(newValue);
                if (!correctedDate) {
                    scope.picker.date = scope.date;
                    return;
                }

                if (correctedDate != scope.picker.date) {
                    scope.picker.date = correctedDate;
                }

                scope.date = correctedDate;

                if (scope.onDateChange) {
                    scope.onDateChange({
                        date: correctedDate
                    });
                }
            }

            scope.clickInput = function () {
                $("#" + scope.datePickerId).datepicker("show");
            }

            function validateDateByFormat(date, format) {
                var dateFormatForMoment = format.toUpperCase();
                var newDate = moment(date, dateFormatForMoment).format(dateFormatForMoment);
                var origDateForCheck = date.replace(/((\D)?0+(\d+))/g, "$2$3");
                var newDateForCheck = newDate.replace(/((\D)?0+(\d+))/g, "$2$3");
                return newDateForCheck === origDateForCheck;
            }

            function tryCorrectDate(dontShowError) {
                var correctedDate = correctDate(scope.date, dontShowError);

                scope.picker.date = correctedDate;

                lastDateTime = scope.picker.date;

                if (scope.date != correctedDate) {
                    scope.date = correctedDate;

                    if (scope.onDateChange) {
                        scope.onDateChange({
                            date: correctedDate
                        });
                    }
                }
            }

            function correctDate(date, dontShowError) {
                if (!date || scope.forceDateChange) return scope.date;

                if (!isValidDate(date)) {
                    console.warn("Invalid date '" + date + "', reverting to " + scope.date + "...");
                    date = scope.date;
                }

                var minDate = scope.minDate ? getDate(scope.minDate, true) : null;
                var maxDate = scope.maxDate ? getDate(scope.maxDate, true) : null;
                var dateObj = getDate(date, true);

                if (minDate && dateObj < minDate) {
                    if (!dontShowError) {
                        $rootScope.showError(L.tsq("Date is out of range") + " - " + date + " < " + scope.minDate);
                        console.error("Coming from datepicker " + scope.datePickerId, scope);
                    }
                    return scope.minDate;
                }
                if (maxDate && dateObj > maxDate) {
                    if (!dontShowError) {
                        $rootScope.showError(L.tsq("Date is out of range") + " - " + date + " > " + scope.maxDate);
                        console.error("Coming from datepicker " + scope.datePickerId, scope);
                    }
                    return scope.maxDate;
                }
                return date;
            }

            var destroyDateWatch = scope.$watch('date', function (newValue, oldValue) {
                //console.error("datePicker watch", newValue, oldValue, angular.copy(scope.picker.date), angular.copy(scope.date));
                if (valueFilled(newValue) && newValue != scope.picker.date) {
                    tryCorrectDate(scope.forceDateChange);
                }
            });

            scope.$on("$destroy", function () {
                destroyDateWatch();
                UniqueIdGenerator.removeId(scope.datePickerId);
            });

            $timeout(function () {
                scope.format = scope.format || 'd.m.yyyy';
                var pickerFormat = scope.format.replace("yyyy", "yy");

                $("#" + scope.datePickerId).datepicker({
                    inline: true,
                    changeYear: true,
                    dateFormat: pickerFormat,
                    onSelect: function (dateText) {
                        scope.onDateChanged(dateText);
                    },
                    beforeShow: function (el, dpInstance) {
                        var minDate = scope.minDate ? getDate(scope.minDate, true) : null;
                        var maxDate = scope.maxDate ? getDate(scope.maxDate, true) : null;
                        $(el).datepicker("option", { minDate: minDate, maxDate: maxDate });
                    },
                }).on('click', function () {
                    var closestParent = $(this).closest(".modal");
                    if (!closestParent) {
                        closestParent = $(this).parent().parent().parent();
                    }
                    $("#ui-datepicker-div").appendTo(closestParent);
                });

                tryCorrectDate(true);
                initialized = true;
            }, 0, false);

            scope.datePickerId = UniqueIdGenerator.generateId();

            scope.label = L.tsq(scope.label) || L.tsq('Date');
            scope.format = scope.format || 'd.m.yyyy';

            scope.picker = {
                date: scope.date
            };

            var lastDateTime = scope.date;

        }
    };
});