//TODO: remove comment after done
//  8a = 08:00 (If last character is a, the time is am) 
//  8p = 20:00 (If last character is p the time is pm)
//  815a / p = 08:15 / 20:15
//  8.15a = 08:15 / 20:15
//  8 = 08:00
//  815 = 08:15
//  8.15 = 08:15
//  8:15 = 08:15
//  08:15 = 08:15

angular.module('dd.ui.timepicker', [])
    .directive('ddTimepicker', TimepickerDirective)
    .factory('timeparserService', timeparserService);

function TimepickerDirective() {

    var directive = {
        restrict: 'A',
        require: 'ngModel',
        replace: true,
        scope: {
        },
        link: function (scope, element, attrs, ngModel) {

            if (!angular.isDefined(ngModel)) {
                return;
            }
            
            //format text going to user (model to view)
            ngModel.$formatters.push(function (value) {
                return value.toUpperCase();
            });

            //format text from the user (view to model)
            ngModel.$parsers.push(function (value) {
                return value.toLowerCase();
            });

        }
    };
    return directive;

}


function timeparserService() {

    var amPmPattern = /^(\d+)(a|p)$/,
        normalTimeFormat = /^([0-9]|0[0-9]|1[0-9]|2[0-3])[.:][0-5][0-9]$/,
        digitsPattern = /^[0-9]+$/; 

    //TODO: validation for invalid cases
    function toModel(input) {
        
        if (normalTimeFormat.test(input)){
            return input;
        }
        
        input = input.trim().toLowerCase().replace('.','').replace(':','');
        
        if (amPmPattern.test(input)) {
            return parseAmPmTime(input, amPmPattern);
        }
        
        if (digitsPattern.test(input)) {
            return parseDigitsTime(input, digitsPattern);
        }
        

        throw 'Invalid time, current val: '+input;
    }

    function parseAmPmTime(input, pattern) {
        var tokens = tokenize(input, pattern),
            timeInfo = getTimeInfoFromInputTokens(tokens[1], tokens[2]);

        return hourToString(timeInfo.hours) + ':' + minutesToString(timeInfo.minutes);
    }
    
    function parseDigitsTime(input) {
        var timeInfo = getTimeInfoFromInputTokens(input, null);
        return hourToString(timeInfo.hours) + ':' + minutesToString(timeInfo.minutes);
    }

    function tokenize(input, pattern) {
        return pattern.exec(input);
    }

    function getTimeInfoFromInputTokens(tokenPart, mode) {
        var val = parseInt(tokenPart),
            hours = 0,
            minutes = 0;

        if (val <= 24) {
            hours = val;
        } else if (val > 24 && val <= 999) {
            
            hours = parseInt(tokenPart[0]);
            minutes = parseInt(tokenPart.substr(1, 3));
            
        } else if (val > 24 && val <= 9999) {
            
            hours = parseInt(tokenPart.substr(0, 2));
            minutes = parseInt(tokenPart.substr(2, 4));
            
        }
        
        if (mode === 'p') {
            hours += 12;
        }
        
        return {
            hours: hours,
            minutes: minutes
        };
    }
    
    function hourToString(hour) {
        return hour < 10 ? '0' + hour : hour.toString();
    }
    
    function minutesToString(minutes) {
        return minutes < 10 ? '0' + minutes : minutes.toString();
    }

    return {
        toModel: toModel
    };

}

@@ -1,287 +1,4 @@
-//TODO: remove comment after done%0A//  8a = 08:00 (If last character is a, the time is am) %0A//  8p = 20:00 (If last character is p the time is pm)%0A//  815a / p = 08:15 / 20:15%0A//  8.15a = 08:15 / 20:15%0A//  8 = 08:00%0A//  815 = 08:15%0A//  8.15 = 08:15%0A//  8:15 = 08:15%0A//  08:15 = 08:15%0A
 %0Aang
@@ -140,16 +140,70 @@
 vice);%0A%0A
+%0ATimepickerDirective.$inject = %5B'timeparserService'%5D;%0A
 function
@@ -223,16 +223,33 @@
 rective(
+timeparserService
 ) %7B%0A%0A   
@@ -431,161 +431,49 @@
 ) %7B%0A
-%0A            if (!angular.isDefined(ngModel)) %7B%0A                return;%0A            %7D%0A            %0A            //format text going to user (model to view
+            %0A            //(view to model
 )%0A  
@@ -495,15 +495,12 @@
 el.$
-formatt
+pars
 ers.
@@ -550,26 +550,39 @@
 urn 
-value.toUpperCase(
+timeparserService.toModel(value
 );%0A 
@@ -588,32 +588,44 @@
             %7D);%0A
+            
 %0A            //f
@@ -625,52 +625,95 @@
     
-//format text from the user (view to m
+element.on('blur', toModelTime);%0A            %0A            function toM
 odel
-)%0A
+Time() %7B%0A    
     
@@ -733,39 +733,69 @@
 el.$
-parsers.push(function (v
+setViewValue(timeparserService.toModel(ngModel.$modelV
 alue)
- %7B
+);
 %0A   
@@ -811,51 +811,115 @@
     
-return value.toLowerCase();%0A            %7D);
+ngModel.$render();%0A            %7D%0A            %0A            //TODO: check about validations like min/max etc.
 %0A%0A  
@@ -929,24 +929,29 @@
    %7D%0A    %7D;%0A
+    %0A
     return d
@@ -964,16 +964,137 @@
 ve;%0A%0A%7D%0A%0A
+//TODO: grunt compile files in wrong order if this service will be putted in separate file. Need to fix this global issue
 %0Afunctio
@@ -1266,17 +1266,16 @@
 0-9%5D+$/;
- 
 %0A%0A    //
@@ -1340,32 +1340,97 @@
 put) %7B%0A        %0A
+        if(!input) %7B%0A            return null;%0A        %7D%0A        %0A
         if (norm

update view value on blur