'use strict';

var PRISTINE_CLASS = 'ng-pristine',
    DIRTY_CLASS = 'ng-dirty';

var Module = angular.module('datePicker');

Module.constant('dateTimeConfig', {
    template: function (attrs) {
        return '' +
            '<div ' +
            'date-picker="' + attrs.ngModel + '" ' +
            (attrs.view ? 'view="' + attrs.view + '" ' : '') +
            (attrs.maxView ? 'max-view="' + attrs.maxView + '" ' : '') +
            (attrs.template ? 'template="' + attrs.template + '" ' : '') +
            (attrs.minView ? 'min-view="' + attrs.minView + '" ' : '') +
            (attrs.partial ? 'partial="' + attrs.partial + '" ' : '') +
            'class="dropdown-menu"></div>';
    },
    format: 'yyyy-MM-dd HH:mm',
    views: ['date', 'year', 'month', 'hours', 'minutes'],
    dismiss: false,
    position: 'relative'
});

Module.directive('dateTimeAppend', function () {
    return {
        link: function (scope, element) {
            element.bind('click', function () {
                element.find('input')[0].focus();
            });
        }
    };
});

Module.directive('dateTime', ['$compile', '$document', '$filter', 'dateTimeConfig', '$parse', function ($compile, $document, $filter, dateTimeConfig, $parse) {
    var body = $document.find('body');
    var dateFilter = $filter('date');

    return {
        require: 'ngModel',
        scope:true,
        link: function (scope, element, attrs, ngModel) {
            var format = attrs.format || dateTimeConfig.format;
            var parentForm = element.inheritedData('$formController');
            var views = $parse(attrs.views)(scope) || dateTimeConfig.views.concat();
            var view = attrs.view || views[0];
            var index = views.indexOf(view);
            var dismiss = attrs.dismiss ? $parse(attrs.dismiss)(scope) : dateTimeConfig.dismiss;
            var picker = null;
            var position = attrs.position || dateTimeConfig.position;
            var container = null;

            if (index === -1) {
                views.splice(index, 1);
            }

            views.unshift(view);


            function formatter(value) {
                return dateFilter(value, format);
            }

            function parser() {
                return ngModel.$modelValue;
            }

            ngModel.$formatters.push(formatter);
            ngModel.$parsers.unshift(parser);


            var template = dateTimeConfig.template(attrs);

            function updateInput(event) {
                event.stopPropagation();
                if (ngModel.$pristine) {
                    ngModel.$dirty = true;
                    ngModel.$pristine = false;
                    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);
                    if (parentForm) {
                        parentForm.$setDirty();
                    }
                    ngModel.$render();
                }
            }

            function clear() {
                if (picker) {
                    picker.remove();
                    picker = null;
                }
                if (container) {
                    container.remove();
                    container = null;
                }
            }

            function showPicker() {
                if (picker) {
                    return;
                }
                // create picker element
                picker = $compile(template)(scope);
                scope.$digest();

                scope.$on('setDate', function (event, date, view) {
                    updateInput(event);
                    if (dismiss && views[views.length - 1] === view) {
                        clear();
                    }
                });

                scope.$on('$destroy', clear);

                // move picker below input element

                if (position === 'absolute') {
                    var pos = angular.extend(element.offset(), { height: element[0].offsetHeight });
                    picker.css({ top: pos.top + pos.height, left: pos.left, display: 'block', position: position});
                    body.append(picker);
                } else {
                    // relative
                    container = angular.element('<div date-picker-wrapper></div>');
                    element[0].parentElement.insertBefore(container[0], element[0]);
                    container.append(picker);
//          this approach doesn't work
//          element.before(picker);
                    picker.css({top: element[0].offsetHeight + 'px', display: 'block'});
                }

                picker.bind('mousedown', function (evt) {
                    evt.preventDefault();
                });
            }

            element.bind('focus', showPicker);
            element.bind('blur', clear);
        }
    };
}]);