var backlog = angular.module('backlog',['ui.bootstrap','ngStorage']);

backlog.controller('backlogControl', function($scope, $localStorage, $http, $timeout){

    $scope.config       = config;
    $scope.tabs         = tabs;      
    $scope.alertMessage = null;
    $scope.alertClass   = null;
    $scope.showAlert    = false;
    $scope.contentDivs  = {};
    for (item in $scope.tabs){
        $scope.contentDivs[$scope.tabs[item]] = false;
    };
    $scope.contentDivs[tabs[0]] = true; 
    $scope.alertLock     = false;
    $scope.showAddStory  = false;
    $scope.showAddTask   = false;
    $scope.showAddSprint = false;
    $scope.stories       = [];
    $scope.tasks         = [];
    $scope.taskSet       = [];
    $scope.sprints       = [];
    $scope.meetings      = [];
    $scope.editStories   = {};
    $scope.tabIds        = tabIds;
    $scope.priorities    = priorities;
    $scope.classes       = classes;
    $scope.keys          = keys;
    $scope.sprintDays    = config.sprintDays;
    $scope.maxAllocation = config.maxAllocation;
    $scope.engineers     = [];
    $scope.sprintStories = []; 
      
    $scope.cleanStory = function(){
        $scope.story = {
            'id':           $scope.getId('stories'),
            'story':        null,
            'weight':       1,
            'dependencies': 'No',
            'type':         'Functional',
            'build':        null,
            'mission':      'Yes',
            'delivered':    'Yes'
        };
    };
  
    $scope.cleanMeeting = function(){
        $scope.meeting = {
            'sprint':    1,
            'comments':  null
        };
    };
 
    $scope.updateEngineers = function(task){
        if ($scope.engineers.length > 0){
            for (engineer in $scope.engineers){
                if ($scope.engineers[engineer].engineer == task.engineer){
                    return false;
                }
            }
            $scope.engineers.push({'engineer': task.engineer, 
            'progress': $scope.makeRange($scope.sprintDays,0)});
        }
        $scope.engineers.push({'engineer': task.engineer, 'progress': $scope.makeRange($scope.sprintDays,0)});
        $localStorage.engineers = $scope.engineers;
    };
  
    $scope.exportProject = function(){
        project = { 
            'backlogMap':     $scope.stories,
            'productBacklog': $scope.tasks,
            'sprintBacklog':  $scope.sprints,
            'standupAgenda':  $scope.meetings
        };
        var link   = document.createElement("a");
        link.href  = "data:text/plain;base64," + btoa(JSON.stringify(project, null, 4));
        link.style = "visibility:hidden";
        link.download = moment().format("DDMMYYYYhhmmss"); + ".json";
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
    };

    $scope.updateEngineersProgress = function(taskId){
        var taskEngineer = null;
        var task         = null;
        for (task in $scope.tasks){
            if ($scope.tasks[task].id == taskId){
                taskEngineer = $scope.tasks[task].engineer;
            }
        }
        for (sprint in $scope.sprints){
            if ($scope.sprints[sprint].task.id == taskId){
                task = $scope.sprints[sprint].progress;
            }
        }
        for (engineer in $scope.engineers){
            if ($scope.engineers[engineer].engineer == taskEngineer){
                for (item in $scope.engineers[engineer].progress){
                    $scope.engineers[engineer].progress[item] += task[item];
                }
            }
        }
        $localStorage.engineers = $scope.engineers;
    };
 
    $scope.renewEngineersProgress = function(){
        for (engineer in $scope.engineers){
            $scope.engineers[engineer].progress = $scope.makeRange($scope.sprintDays,0);
        }
        for (task in $scope.tasks){
            $scope.updateEngineersProgress($scope.tasks[task].id);
        }
    };

    $scope.cleanTask = function(){
        $scope.task = {
            'storyId':     1,
            'id':          null,
            'priority':    'Low',
            'status':      0,
            'owner':       null,
            'engineer':    null,
            'class':       'Task',
            'description': null,
            'eta':         1
         };
    };

    $scope.cleanSprint = function(){
        $scope.sprint = {
            'id':       1,
            'storyId':  null,
            'task':     {'id': null, 'description': null},
            'progress': $scope.makeRange($scope.sprintDays,0)
        };
        $scope.taskSet.length = 0;
    };
    
    $scope.loadProgress = function(value,collection){
        for (item in collection){
            if (collection[item].task.id == value.task.id){
                return collection[item].progress;
            }
        }
    };
 
    $scope.validateCapacity = function(){
        var results = '';
        for (engineer in $scope.engineers){
            for (day in $scope.engineers[engineer].progress){
                if ($scope.engineers[engineer].progress[day] > $scope.maxAllocation){
                    results += ('engineer: ' + $scope.engineers[engineer].engineer + 
                    ' time allocation was exceeded for day: ' + (parseInt(day) + 1)  + ' by ' +
                    (parseInt($scope.engineers[engineer].progress[day]) - $scope.maxAllocation) +
                    ' hours. ');
                }
            }
        }
        if (results != ''){
            $scope.setAlert(results,'danger');
        }else{
            $scope.setAlert('Everything looks fine','success');
        }
    };

    $scope.collectStories = function(){
        $scope.sprintStories.length = 0;
        for (sprint in $scope.sprints){
            var sprintFound = false;
            for (sstories in $scope.sprintStories){
               if ($scope.sprints[sprint].id == $scope.sprintStories[sstories].id){
                   sprintFound = true;
               }
            }
            if (!sprintFound){
                $scope.sprintStories.push({'id': $scope.sprints[sprint].id, 'stories': 0});
            }
        }
        for (task in $scope.tasks){
            for (sprint in $scope.sprints){
                if ($scope.tasks[task].id == $scope.sprints[sprint].task.id){
                    for (ssprint in $scope.sprintStories){
                        if($scope.sprintStories[ssprint].id == $scope.sprints[sprint].id){
                            $scope.sprintStories[ssprint].stories += 1;
                        }
                    }
                }
            }
        }
        $scope.plotBurndown($scope.sprintStories); 
    };

    $scope.loadableSprint = function(sprint){
        var validStory = false;
        var validTask  = false;
        for (task in $scope.tasks){
            for(story in $scope.stories){
                if ($scope.stories[story].id == $scope.tasks[task].storyId){
                    if (sprint.storyId == $scope.stories[story].id){
                        validStory = true;
                    }
                }
            }
            if($scope.tasks[task].id == sprint.task.id){
                validTask = true;
            }
        }
        if(!validStory){
            $scope.setAlert('Story id not matching story-task relationship or was not found in collections',
            'danger');
            return false;
        }
        if(!validTask){
            $scope.setAlert('No task id could be associated to the task: "' + sprint.task.description + 
            '" in this sprint','danger');
            return false;
        }
        for (item in sprint.progress){
            if (sprint.progress[item] < 0 || sprint.progress[item] > 24){
                $scope.setAlert('Invalid effort detected: ' + sprint.progress[item] + ', at Sprint: ' +
                sprint.id + ' on day: ' + (parseInt(item) + 1),'danger');
                return false;
            }
        }
        if(sprint.progress.length != $scope.sprintDays){
            $scope.setAlert('Sprint range mismatches sprint days, check config','danger');
            return false;
        }
        return true;
    };
 
    $scope.makeRange = function(size,zero){
        var array = [];
        for (i=1; i<=size; i++){
            if (zero == null){
                array.push(i);
            }else{
                array.push(0);
            }
        }
        return array;
    };

    $scope.updateElement = function(component){
        this.task[component] = document.getElementById( component + '_' + this.$index).value;
    };
    
    $scope.updateProgress = function(id,taskId,component){
        var progressField = document.getElementById( component + '_' + id + '_' + taskId +
        '_' + this.$index);
        if (progressField.value == "" || !progressField){ progressField.value = 0; }
        this.sprint[component][this.$index] = parseInt(progressField.value);
        $scope.renewEngineersProgress();
    };

    $scope.validComments = function(meeting){
       if (!meeting || !('comments' in meeting)){
            $scope.setAlert('The meeting comments are empty','danger');
            return false;
        }else if (meeting && (meeting.comments == "" || meeting.comments == null)){
            $scope.setAlert('The meeting comments are empty','danger');
            return false;
        }
        $scope.saveCollection('meetings',meeting);
    };
 
    $scope.setTasks = function(sprintId,story){
        $scope.taskSet.length = 0;
        for (item in $scope.tasks){
            if($scope.tasks[item].storyId == story){
                var taskFound = false;
                for (sprint in $scope.sprints){
                    if ($scope.sprints[sprint].id == sprintId){
                        if ($scope.sprints[sprint].task.id == $scope.tasks[item].id){
                            taskFound = true;
                        }
                    }
                }
                if (!taskFound){
                    $scope.taskSet.push({'id': $scope.tasks[item].id,'description': $scope.tasks[item].description});
                }
            }
        }
    };
   
    $scope.startProgress = function(){
        $scope.sprint.progress = $scope.makeRange($scope.sprintDays,0);
    };
 
    $scope.editBuild = function(){
        if (this.story.id in $scope.editStories){
            if ($scope.editStories[this.story.id] == true){
                this.story.build = document.getElementById('build_' + this.$index).value;
                $scope.editStories[this.story.id] = false;
            } else{
                $scope.editStories[this.story.id] = true;
            }
        }
    };

    $scope.setAlert = function(message,level){
        switch(level){
            case 'warning': 
                level = 'alert alert-warning';
                break;
            case 'danger':
                level = 'alert alert-danger';
                break;
            case 'success':
                level = 'alert alert-success';
                break;
            default:
                level = 'alert alert-info';
        }
        var sleep = 0;
        if ($scope.alertLock == true){
           sleep = $scope.config.timeout * 500;
        }else{
           $scope.alertLock = true;
        }
        $timeout(function(){$scope.launchAlert(message,level);},sleep);
    };

    $scope.launchAlert = function(message,level){
        $scope.alertClass   = level;
        $scope.alertMessage = message;
        $scope.showAlert    = true;
        $timeout($scope.clearAlert,($scope.config.timeout * 1000));
    };

    $scope.clearAlert = function(){
        if ($scope.alertLock == true){
            $scope.alertMessage = null;
            $scope.alertClass   = null;
            $scope.showAlert    = false;
            $scope.alertLock    = false;
        }
    };

    $scope.canEditBuild = function(){
        if (this.story.id in $scope.editStories){
             return $scope.editStories[this.story.id];
        }
        $scope.setAlert('Mismatch found in the stored story ids and the local items','warning');
        return false;
    };
   
    $scope.loadStories = function(){
        $scope.loadStorage('stories');
        $scope.mapStoriesEditor();
    };
   
    $scope.loadStorage = function(option){
        if(option in $localStorage){
            if ($localStorage[option].length > 0){
                $scope[option] = $localStorage[option];
            }
        }
    };
  
    $scope.mapStoriesEditor = function(){
        $scope.editStories.length = 0;
        for (item in $scope.stories){
            $scope.editStories[$scope.stories[item].id] = false;
        }
    };
 
    $scope.loadFromFile = function($fileContent){
        try{
            fileStories = JSON.parse($fileContent);
        }
        catch(err){
            $scope.setAlert('Failed to open the selected file / Not compatible JSON format','danger');
            return false;
        }
        $scope.cleanStory();
        for (option in $scope.tabIds){ 
            option = $scope.tabIds[option];
            if ( option in fileStories != true || fileStories[option].length == 0){
                $scope.setAlert('Options for the tab ' + option + ' not found in file','warning');
                return false;
            }
            for (item in fileStories[option]){
                for (key in $scope.keys[option]){
                    key = $scope.keys[option][key];
                    if (key in fileStories[option][item] == false){
                        $scope.setAlert('Missing key in file, check config.js','danger');
                        return false;
                    }
                }
            }
        }
        $scope.clearUp('stories',fileStories.backlogMap);
        $scope.clearUp('tasks',fileStories.productBacklog);
        $scope.clearUp('sprints',fileStories.sprintBacklog);
        $scope.clearUp('meetings',fileStories.standupAgenda);
        $scope.clearEngineers();
        $scope.cleanStory();
        $scope.cleanTask();
        $scope.cleanSprint();
        $scope.cleanMeeting();
        $scope.mapStoriesEditor();
        for (item in $scope.sprints){
            if ($scope.loadableSprint($scope.sprints[item]) == false){
                return false;
            }
        }
        for (task in $scope.tasks){
            $scope.updateEngineers($scope.tasks[task]);
        }
        for (sprint in $scope.sprints){
            $scope.updateEngineersProgress($scope.sprints[sprint].task.id);
        }
        $scope.collectStories();
    };

    $scope.clearEngineers = function(){
        delete $localStorage.engineers;
        $scope.engineers.length = 0;
    }
  

    $scope.clearUp = function(option,data){
        $scope[option].length = 0;
        delete $localStorage[option];
        $scope[option]        = data;
        $localStorage[option] = $scope[option];
    };

    $scope.getId = function(option){
        var top = 0;
        for (item in $scope[option]){
            if ($scope[option][item].id > top){
                top = $scope[option][item].id;
            }
        }
        return (top + 1);
    };
 
    $scope.saveCollection = function(type,item){
        $scope[type].push(item);
        return false;
        $localStorage[type] = $scope[type];
    };

    $scope.saveStory = function(type,item){
        $scope.saveCollection(type,item);
        $scope.mapStoriesEditor();
    };

    $scope.showDiv = function(tab){
        if (tab in $scope.contentDivs){
            for (div in $scope.contentDivs){
                if (div != tab){
                    $scope.contentDivs[div] = false;
                } else {
                    $scope.contentDivs[div] = true;
                } 
            }
        }
    }

    $scope.toggle = function(value){
        return !value;
    }

    $scope.plotBurndown = function(sprintStories){
        var sprints = [0];
        var stories = [0];
        for (ssprint in sprintStories){
           sprints.push(sprintStories[ssprint].id);
           stories.push(sprintStories[ssprint].stories);
        }
        var data = {
            labels: sprints,
            datasets: [
                {
                    label: "Burndown Chart",
                    fillColor: "rgba(151,187,205,0.2)",
                    strokeColor: "rgba(151,187,205,1)",
                    pointColor: "rgba(151,187,205,1)",
                    pointStrokeColor: "#fff",
                    pointHighlightFill: "#fff",
                    pointHighlightStroke: "rgba(220,220,220,1)",
                    data: stories
                }
            ]
        }
        var options = {
            scaleShowGridLines : true,
            scaleGridLineColor : "rgba(0,0,0,.05)",
            scaleGridLineWidth : 1,
            scaleShowHorizontalLines: true,
            scaleShowVerticalLines: true,
            bezierCurve : true,
            bezierCurveTension : 0.4,
            pointDot : true,
            pointDotRadius : 4,
            pointDotStrokeWidth : 1,
            pointHitDetectionRadius : 20,
            datasetStroke : true,
            datasetStrokeWidth : 2,
            datasetFill : true,
        };
        var ctx = document.getElementById("burndown").getContext("2d");
        var myLineChart = new Chart(ctx).Line(data, options);
        Chart.defaults.global.animation       = true;
        Chart.defaults.global.showScale       = true;
        Chart.defaults.global.scaleShowLabels = true;
        Chart.defaults.global.scaleLabel      = "<%=value%>";
        Chart.defaults.global.scaleFontSize   = 12;
        Chart.defaults.global.scaleFontStyle  = "normal";
        Chart.defaults.global.scaleFontColor  = "#666";
        myLineChart.update();
    };

});

backlog.directive('onReadFile', function ($parse) {
    return {
        restrict: 'A',
        scope: false,
        link: function(scope, element, attrs) {
            var fn = $parse(attrs.onReadFile);
            element.on('change', function(onChangeEvent) {
                var reader = new FileReader();
                reader.onload = function(onLoadEvent) {
                    scope.$apply(function() {
                        fn(scope, {$fileContent:onLoadEvent.target.result});
                    });
                };
                reader.readAsText((onChangeEvent.srcElement || onChangeEvent.target).files[0]);
            });
        }
    };
});
