text: 'use strict';
  
  /**
   * Document edition controller.
   */
  angular.module('docs').controller('DocumentEdit', function($rootScope, $scope, $q, $http, $state, $stateParams, Restangular, $translate) {
    // Alerts
    $scope.alerts = [];
  
    // Vocabularies
    $scope.vocabularies = [];
  
    // Orphan files to add
    $scope.orphanFiles = [];
    if ($stateParams.files) {
      $scope.orphanFiles = _.isArray($stateParams.files) ? $stateParams.files : [ $stateParams.files ];
    }
  
    /**
     * Close an alert.
     */
    $scope.closeAlert = function(index) {
      $scope.alerts.splice(index, 1);
    };
  
    /**
     * Returns a promise for typeahead title.
     */
    $scope.getTitleTypeahead = function($viewValue) {
      var deferred = $q.defer();
      Restangular.one('document/list')
      .get({
        limit: 5,
        sort_column: 1,
        asc: true,
        search: $viewValue
      }).then(function(data) {
        deferred.resolve(_.uniq(_.pluck(data.documents, 'title'), true));
      });
      return deferred.promise;
    };
    
    /**
     * Returns true if in edit mode (false in add mode).
     */
    $scope.isEdit = function() {
      return $stateParams.id;
    };
  
    /**
     * Reset the form to add a new document.
     */
    $scope.resetForm = function() {
      var language = 'eng';
      if ($rootScope.app && $rootScope.app.default_language) {
        language = $rootScope.app.default_language;
      }
  
      $scope.document = {
        tags: [],
        relations: [],
        language: language,
        metadata: []
      };
  
      // Get custom metadata list
      Restangular.one('metadata').get({
        sort_column: 1,
        asc: true
      }).then(function(data) {
        $scope.document.metadata = data.metadata;
      });
  
      if ($scope.navigatedTag) {
        $scope.document.tags.push($scope.navigatedTag);
      }
  
      $scope.newFiles = [];
  
      if ($scope.form) {
        $scope.form.$setPristine();
      }
    };
  
    /**
     * Edit a document.
     * Workflow:
     * Edit/add the file -> upload local files -> attach orphan files -> redirect to edited document or stay if adding
     */
    $scope.edit = function() {
      var promise = null;
      var document = angular.copy($scope.document);
      
      // Transform date to timestamp
      if (document.create_date instanceof Date) {
        document.create_date = document.create_date.getTime();
      }
      
      // Extract ids from tags
      document.tags = _.pluck(document.tags, 'id');
  
      // Extract ids from relations (only when our document is the source)
      document.relations = _.pluck(_.where(document.relations, { source: true }), 'id');
  
      // Extract custom metadata values
      var metadata = _.reject(document.metadata, function (meta) {
        return _.isUndefined(meta.value) || meta.value === '' || meta.value == null;
      });
      document.metadata_id =  _.pluck(metadata, 'id');
      document.metadata_value =  _.pluck(metadata, 'value');
      document.metadata_value = _.map(document.metadata_value, function (val) {
        if (val instanceof Date) {
          return val.getTime();
        }
        return val;
      });
  
      // Send to server
      if ($scope.isEdit()) {
        promise = Restangular.one('document', $stateParams.id).post('', document);
      } else {
        promise = Restangular.one('document').put(document);
      }
  
      // Attach orphan files after edition
      var attachOrphanFiles = function(data) {
        var promises = [];
        _.each($scope.orphanFiles, function(fileId) {
          promises.push(Restangular.one('file/' + fileId).post('attach', { id: data.id }));
        });
        $scope.orphanFiles = [];
        return $q.all(promises);
      };
      
      // Upload files after edition
      promise.then(function(data) {
        $scope.fileProgress = 0;
        
        // When all files upload are over, attach orphan files and move on
        var navigateNext = function() {
          attachOrphanFiles(data).then(function() {
            // Open the edited/created document
            $scope.pageDocuments();
            $state.go('document.view', { id: data.id });
          });
        };
        
        if (!$scope.newFiles || $scope.newFiles.length === 0) {
          navigateNext();
        } else {
          $scope.fileIsUploading = true;
          $rootScope.pageTitle = '0% - ' + $rootScope.appName;
          
          // Send a file from the input file array and return a promise
          var sendFile = function(key) {
            var deferred = $q.defer();
            var getProgressListener = function(deferred) {
              return function(event) {
                deferred.notify(event);
              };
            };
  
            // Build the payload
            var file = $scope.newFiles[key];
            var formData = new FormData();
            formData.append('id', data.id);
            formData.append('file', file, encodeURIComponent(file.name));
  
            // Send the file
            $.ajax({
              type: 'PUT',
              url: '../api/file',
              data: formData,
              cache: false,
              contentType: false,
              processData: false,
              success: function(response) {
                deferred.resolve(response);
              },
              error: function(jqXHR) {
                deferred.reject(jqXHR);
              },
              xhr: function() {
                var myXhr = $.ajaxSettings.xhr();
                myXhr.upload.addEventListener(
                    'progress', getProgressListener(deferred), false);
                return myXhr;
              }
            });
  
            // Update progress bar and title on progress
            var startProgress = $scope.fileProgress;
            deferred.promise.then(function(data) {
              // New file uploaded, increase used quota
              $rootScope.userInfo.storage_current += data.size;
            }, function(data) {
              // Error uploading a file, we stop here
              $scope.alerts.unshift({
                type: 'danger',
                msg: $translate.instant('document.edit.document_' + ($scope.isEdit() ? 'edited' : 'added') + '_with_errors')
                  + (data.responseJSON && data.responseJSON.type === 'QuotaReached' ? (' - ' + $translate.instant('document.edit.quota_reached')) : '')
              });
  
              // Reset view and title
              $scope.fileIsUploading = false;
              $scope.fileProgress = 0;
              $rootScope.pageTitle = $rootScope.appName;
            }, function(e) {
              var done = 1 - (e.total - e.loaded) / e.total;
              var chunk = 100 / _.size($scope.newFiles);
              $scope.fileProgress = startProgress + done * chunk;
              $rootScope.pageTitle = Math.round($scope.fileProgress) + '% - ' + $rootScope.appName;
            });
  
            return deferred.promise;
          };
          
          // Upload files sequentially
          var key = 0;
          var then = function() {
            key++;
            if ($scope.newFiles[key]) {
              sendFile(key).then(then);
            } else {
              $scope.fileIsUploading = false;
              $scope.fileProgress = 0;
              $rootScope.pageTitle = $rootScope.appName;
              navigateNext();
            }
          };
          sendFile(key).then(then);
        }
      });
    };
    
    /**
     * Cancel edition.
     */
    $scope.cancel = function() {
      if ($scope.isEdit()) {
        $state.go('document.view', { id: $stateParams.id });
      } else {
        $state.go('document.default');
      }
    };
  
    /**
     * In edit mode, load the current document.
     */
    if ($scope.isEdit()) {
      Restangular.one('document', $stateParams.id).get().then(function(data) {
        $scope.document = data;
      });
    } else {
      $scope.resetForm();
    }
  
    // Load vocabularies
    $scope.loadVocabulary = function(name) {
      Restangular.one('vocabulary', name).get().then(function(result) {
        $scope.vocabularies[name] = result.entries;
      });
    };
    $scope.loadVocabulary('type');
    $scope.loadVocabulary('coverage');
    $scope.loadVocabulary('rights');
  });