'use strict';

/* Controllers */
var senTestKitControllers = angular.module('senTestKitControllers');



/* ProjectDetailCtrl controller */
senTestKitControllers.controller('ProjectDetailCtrl', ['$rootScope', '$scope', '$timeout', '$interval', '$location', '$routeParams', 'Project', 'Application', 'TestScript', 'DeviceModel', 'filterFilter', 'TestRequest', '$filter',
  function($rootScope, $scope, $timeout, $interval, $location, $routeParams, Project, Application, TestScript, DeviceModel, filterFilter, TestRequest, $filter) {
    
    $rootScope.willRefreshDeviceModels = false;
    $rootScope.willRefreshDeviceModelsInRunTest = false; // TODO: change to true in production
    $rootScope.willRefreshTestingResult = false;

    $rootScope.leftMenuItem = "Projects";
    
    $scope.projectId = $routeParams.projectId;

    // Overview tab
    function getProjectData() {
      Project.get($scope.projectId, function(project) {
        $scope.project = project;
      });
    }

    getProjectData();
    
    $scope.prepareForUpdateProject = function() {
      $scope.selectedProject = angular.copy($scope.project);
    }
    
    $scope.updateProject = function() {
      Project.update($scope.selectedProject.projectId, $scope.selectedProject.projectName, $scope.selectedProject.projectDesc, function(project) {
        $scope.project = project;
      });
    }

    $scope.deleteProject = function() {
      Project.delete($scope.projectId, function() {
        $timeout(function () {
          goToProjectList();
        }, 300);
      });
    }

    function goToProjectList() {
      $location.path('/projects');
    };

    
    // Applications tab
    $scope.applicationOrderProp = '';
    $scope.applicationFilter = '';

    $scope.filterApplications = function() {
      $scope.filteredApplications = filterFilter($scope.applications, $scope.applicationFilter);
      $scope.applicationListPagingInfo = new PagingInfo($scope.filteredApplications, $rootScope.pagingSize.applicationList);
      $scope.goToApplicationPage(1);
    }

    $scope.goToApplicationPage = function(pageIndex) {
      $scope.pagedApplications = $scope.applicationListPagingInfo.goToPage(pageIndex);
    }

    $scope.rsFilterApplications = function() {
      $scope.rsFilteredApplications = filterFilter($scope.applications, $scope.rsApplicationFilter);
    }
    
    function queryApplications() {
      Application.query($scope.projectId, function(applications) {
        $scope.applications = applications;
        $scope.rsFilterApplications();
        $scope.filterApplications();
      });
    }

    queryApplications();

    $scope.prepareForUploadApplication = function() {
      $scope.applicationName = "";
      $scope.applicationDesc = "";
      $scope.applicationFile = undefined;
      clearInputFile();
      $scope.uploadApplicationForm.$setPristine();
    }    
    
    $scope.addApplication = function() {
      Application.add($scope.projectId, $scope.applicationName, $scope.applicationDesc, $scope.applicationFile, function(application) {
        queryApplications();
      });
    }

    $scope.isNoApplicationSelected = true;
    $scope.chkApplication = {}; // Must have this for input checkbox ng-model works
    
    $scope.handleApplicationSelection = function(application) {
      var alreadySelected = checkItemInArray($scope.selectedApplications, application, function(app1, app2) {
        return (app1.applicationId == app2.applicationId);
      });

      if (alreadySelected) {
        $scope.selectedApplications = filterItemsInArray($scope.selectedApplications, application, function(app1, app2) {
          return (app1.applicationId != app2.applicationId);
        });
      } else {
        $scope.selectedApplications = pushItemToArray($scope.selectedApplications, application);
      }

      $scope.isNoApplicationSelected = angular.isUndefined($scope.selectedApplications);
    }

    $scope.deleteApplications = function() {
      if (angular.isUndefined($scope.selectedApplications)) return;

      angular.forEach($scope.selectedApplications, function(application, key) {
        Application.delete(application.applicationId, function() {
          queryApplications();
        });
      });
    }


    // Test Script tab
    $scope.testScriptOrderProp = '';
    $scope.testScriptFilter = '';

    $scope.filterTestScripts = function() {
      $scope.filteredTestScripts = filterFilter($scope.testScripts, $scope.testScriptFilter);
      $scope.testScriptListPagingInfo = new PagingInfo($scope.filteredTestScripts, $rootScope.pagingSize.testScriptList);
      $scope.goToTestScriptPage(1);
    }

    $scope.goToTestScriptPage = function(pageIndex) {
      $scope.pagedTestScripts = $scope.testScriptListPagingInfo.goToPage(pageIndex);
    }

    $scope.rsFilterTestScripts = function() {
      if (angular.isDefined($scope.rsSelectedApplication)) {
        var rsFilteredTestScripts = filterFilter($scope.testScripts, $scope.rsTestScriptFilter);
        $scope.rsFilteredTestScripts = filterItemsInArray(rsFilteredTestScripts, $scope.rsSelectedApplication.platform, function(pl, ts) {
          return (pl == ts.platform);
        });
      } else {
        $scope.rsFilteredTestScripts = undefined;
      }      
    }

    function queryTestScripts() {
      TestScript.query($scope.projectId, function(testScripts) {
        $scope.testScripts = testScripts;
        $scope.filterTestScripts();
        $scope.rsFilterTestScripts();
      });
    }

    queryTestScripts();
    
    $scope.prepareForUploadTestScript = function() {
      $scope.testScriptName = "";
      $scope.testScriptDesc = "";
      $scope.platform = "iOS";
      $scope.testScriptFile = undefined;
      clearInputFile();
      $scope.uploadTestScriptForm.$setPristine();
    }

    $scope.addTestScript = function() {
      TestScript.add($scope.projectId, $scope.testScriptName, $scope.testScriptDesc, $scope.platform, $scope.testScriptFile, function(testScript) {
        queryTestScripts();
      });
    }

    $scope.isNoTestScriptSelected = true;
    $scope.chkTestScript = {}; // Must have this for input checkbox ng-model works

    $scope.handleTestScriptSelection = function(testScript) {
      var alreadySelected = checkItemInArray($scope.selectedTestScripts, testScript, function(ts1, ts2) {
        return (ts1.testScriptId == ts2.testScriptId);
      });

      if (alreadySelected) {
        $scope.selectedTestScripts = filterItemsInArray($scope.selectedTestScripts, testScript, function(ts1, ts2) {
          return (ts1.testScriptId != ts2.testScriptId);
        });
      } else {
        $scope.selectedTestScripts = pushItemToArray($scope.selectedTestScripts, testScript);        
      }

      $scope.isNoTestScriptSelected = angular.isUndefined($scope.selectedTestScripts);
    }

    $scope.deleteTestScripts = function() {
      if (angular.isUndefined($scope.selectedTestScripts)) return;

      angular.forEach($scope.selectedTestScripts, function(testScript, key) {
        TestScript.delete(testScript.testScriptId, function() {
          queryTestScripts();
        });
      });
    }


    // Run Test tab
    $scope.rsFilterDeviceModels = function() {
      if (angular.isDefined($scope.rsSelectedApplication)) {
        // Filter by platform first
        var modelsByPlatforms = [];
        var platform = $scope.rsSelectedApplication.platform;        
        angular.forEach($scope.deviceModels, function(deviceModel, deviceModelKey) {
          if ((deviceModel.model.platform == platform) && (deviceModel.deviceReady)) {
            if (deviceModel.model.photoPathUrl.startsWith('/')) {
              deviceModel.model.photoPathUrl = deviceModel.model.photoPathUrl.substring(1);
            }
            modelsByPlatforms.push({
              modelTestingId: deviceModel.modelTestingId,
              modelId:        deviceModel.model.modelId,
              modelLabel:     deviceModel.model.modelName,
              photoUrl:       deviceModel.model.photoPathUrl,
              osVersion:      deviceModel.os.osVersion,
              manufacturer:   deviceModel.model.manufacturer.manufacturerName
            });
          }
        });
        
        // Get all manufactories for "select" control
        var firstManufacturer = "All Manufactories";
        $scope.manufactories = [ firstManufacturer ];
        angular.forEach(modelsByPlatforms, function(deviceModel, key) {
          if ($scope.manufactories.indexOf(deviceModel.manufacturer) < 0) {
            $scope.manufactories.push(deviceModel.manufacturer);
          }
        });
        if ($scope.manufactories.length > 0) {
          if (($scope.rsManufactoryFilter == undefined) || ($scope.manufactories.indexOf($scope.rsManufactoryFilter) < 0)) {
            $scope.rsManufactoryFilter = $scope.manufactories[0];
          }          
        }
        
        // Then filter by selected Manufactory
        var modelsByManufactories = [];
        if ($scope.rsManufactoryFilter == firstManufacturer) {
          modelsByManufactories = modelsByPlatforms;
        } else {
          modelsByManufactories = filterItemsInArray(modelsByPlatforms, $scope.rsManufactoryFilter, function(manufacturer, dm) {
            return (manufacturer == dm.manufacturer);
          });
        }
        
        // Get all OS Versions for "select" control
        var firstOSVersion = "All OS Versions";
        $scope.osVersions = [ firstOSVersion ];
        angular.forEach(modelsByManufactories, function(deviceModel, key) {
          if ($scope.osVersions.indexOf(deviceModel.osVersion) < 0) {
            $scope.osVersions.push(deviceModel.osVersion);
          }
        });
        if ($scope.osVersions.length > 0) {
          if (($scope.rsOSVersionFilter == undefined) || ($scope.osVersions.indexOf($scope.rsOSVersionFilter) < 0)) {
            $scope.rsOSVersionFilter = $scope.osVersions[0];
          }          
        }
        
        // Then, OS Version and free text
        var modelsByOSVersion = [];
        if ($scope.rsOSVersionFilter == firstOSVersion) {
          modelsByOSVersion = modelsByManufactories;
        } else {
          modelsByOSVersion = filterItemsInArray(modelsByManufactories, $scope.rsOSVersionFilter, function(osVersion, dm) {
            return (osVersion == dm.osVersion);
          });
        }
        
        $scope.rsFilteredDeviceModels = filterFilter(modelsByOSVersion, $scope.rsDeviceFilter);

      } else {
        $scope.rsFilteredDeviceModels = undefined;
        $scope.manufactories = undefined;
        $scope.rsManufactoryFilter = undefined;
      }
    }

    function isPlatformChanged(application) {
      if ($scope.rsSelectedApplication == undefined) {
        return true;
      }
      if ($scope.rsSelectedApplication.platform != application.platform) {
        return true;
      } else {
        return false;
      }
    }

    $scope.rsHandleApplicationSelection = function(application) {
      if (($scope.rsSelectedApplication == undefined)
        || ($scope.rsSelectedApplication.applicationId != application.applicationId)) {
        // Clear selected of test script / devices
        // since when platform is changed, those test scripts / devices
        // no longer available
        if (isPlatformChanged(application)) {
          $scope.rsSelectedTestScript = undefined;
          $scope.rsSelectedDeviceModels = undefined;
        }
        $scope.rsSelectedApplication = application;
      } else {
        $scope.rsSelectedApplication = undefined;
        $scope.rsSelectedTestScript = undefined;
        $scope.rsSelectedDeviceModels = undefined;
      }

      $scope.rsFilterTestScripts();
      $scope.rsFilterDeviceModels();
    }

    $scope.rsHandleTestScriptSelection = function(testScript) {
      if (($scope.rsSelectedTestScript == undefined)
        || ($scope.rsSelectedTestScript.testScriptId != testScript.testScriptId)) {
        $scope.rsSelectedTestScript = testScript;
      } else {
        $scope.rsSelectedTestScript = undefined;
      }
    }
    
    function queryDeviceModels() {
      DeviceModel.query(function(deviceModels) {
        $scope.deviceModels = deviceModels;
        $scope.rsFilterDeviceModels();
      });
      if ($rootScope.willRefreshDeviceModelsInRunTest) {
        $timeout(function () {
          queryDeviceModels();
        }, 5000);
      }
    }

    queryDeviceModels();

    $scope.checkDeviceModelInArray = function(deviceModel) {
      return checkItemInArray($scope.rsSelectedDeviceModels, deviceModel, function(dm1, dm2) {
        return (dm1.modelTestingId == dm2.modelTestingId);
      });
    }

    $scope.rsHandleDeviceModelSelection = function(deviceModel) {
      var alreadySelected = $scope.checkDeviceModelInArray(deviceModel);

      if (alreadySelected) {
        $scope.rsSelectedDeviceModels = filterItemsInArray($scope.rsSelectedDeviceModels, deviceModel, function(dm1, dm2) {
          return (dm1.modelTestingId != dm2.modelTestingId);
        });
      } else {
        $scope.rsSelectedDeviceModels = pushItemToArray($scope.rsSelectedDeviceModels, deviceModel);        
      }
    }

    var notDoneTestRequestCount = 0;
    $scope.requestingTest = false;

    $scope.runTestScript = function() {
      $scope.addTestRequestMessage = "Creating a test request ...";
      
      var modelTestingIds = [];
      angular.forEach($scope.rsSelectedDeviceModels, function(value, key) {
        modelTestingIds.push(value.modelTestingId);
      });
      var modelTesting = modelTestingIds.join(';');
      
      $scope.requestingTest = true; // To show spinner
      var requestTestingSuccess = false;
      TestRequest.add($scope.projectId, $scope.rsSelectedApplication.applicationId, $scope.rsSelectedTestScript.testScriptId, modelTesting, function(testRequest) {
        if (angular.isDefined(testRequest)) {
          $scope.addTestRequestMessage = "Successfully created a test request!";

          notDoneTestRequestCount = notDoneTestRequestCount + 1;
          $rootScope.notDoneTestRequest = "" + notDoneTestRequestCount; // Show on badge

          // Clear selection in case request testing success
          $timeout(function() {
            $scope.addTestRequestMessage = undefined;
            $scope.requestingTest = false; // To hide spinner

            $scope.rsHandleApplicationSelection($scope.rsSelectedApplication);

            $scope.rsSelectedApplication = undefined;
            $scope.rsSelectedTestScript = undefined;
            $scope.rsSelectedDeviceModels = undefined;
          }, 300);

          queryTestRequests();

        } else {
          $scope.addTestRequestMessage = "Failed to create a test request!";
        }
      });
    }

    function queryTestRequests() {
      TestRequest.query($scope.projectId, function(testRequests) {
        $scope.testRequests = $filter('orderBy')(testRequests, '-timeCreate', false);;
        $scope.testRequestPagingInfo = new PagingInfo($scope.testRequests, $rootScope.pagingSize.projectTestRequestList);
        $scope.testRequestPagingInfo.generateIndex(false);
        $scope.goToTestRequestPage(1);
      });
    }

    $scope.testRequests = [];
    $scope.goToTestRequestPage = function(pageIndex) {
      $scope.pagedTestRequests = $scope.testRequestPagingInfo.goToPage(pageIndex);
    }

    queryTestRequests();
  }]);
