app.controller('entityCtrl', function($entity, entityMap, ErrorSvc, $page, mySocket, $window, $routeParams, $controller, $location, $scope, $uibModal, blockUI, inform, $route, NgTableParams) {
  //set scope variables
  $scope.table = {params: null};
  $scope.console = null;
  $scope.entities = entityMap;
  $scope.entityName = $routeParams.entity;
  $scope.lookup = {};
  $scope.items = [];
  $scope.item = {};
  $scope.newFile = {};

  //set scope functions
  $scope.add = function(item) {
    blockUI.start("A enviar dados...");
    $entity.add($routeParams.entity, item)
    .then(function(response) {
      if (item._id) {
        inform.add($scope.entity.title + ' - registo alterado com sucesso!', {ttl: 2000, type: 'info'});
      }
      else {
        inform.add($scope.entity.title + ' - novo registo criado com sucesso!', {ttl: 2000, type: 'info'});
      }
      //$location.path($scope.entityName + "/list");
    })
    .catch(function(response) {
      inform.add(response.data, {ttl: 2000, type: 'danger'});
    })
    .finally(function() {
      blockUI.stop();
    });
  };

  $scope.remove = function(item) {
    blockUI.start("Averiguando eligibilidade de remoção...");

    $entity.remove($routeParams.entity, item)
    .then(function(response) {
      inform.add($scope.entity.title + ' - registo apagado com sucesso!', {ttl: 2000, type: 'info'});
    })
    .catch(function(response) {
      inform.add(response.error ? response.error : response.data, {ttl: 2000, type: 'danger'});
    })
    .finally(function() {
      blockUI.stop();
    });
  };

  $scope.openEdit = function(item) {
    if (!$scope.entity.modal) {
      if (item) {
        $location.path($routeParams.entity + '/edit/' + item._id);
      }
      else {
        $location.path($routeParams.entity + '/edit');
      }

      return;
    }

    setEdit(item);

    var modalInstance = $uibModal.open({
      animation: true,
      templateUrl: 'client/entity/entity.modal.html',
      controller: 'entityModalCtrl',
      size: 'lg',
      backdrop: 'static',
      scope: $scope
    });

    modalInstance.result.then(function(newItem) {
      $scope.add(newItem);
    }, function() {
      inform.add('Alteração ao registo cancelada', {ttl: 2000, type: 'info'});
      $scope.item = {};
    });
  };

  $scope.validate = function() {
    if (typeof $scope.getError === 'function') {
      var response = $scope.getError($scope.item, $scope.items);
      if (response.disabled) {
        $scope.console = response.tooltip;
        return true;
      }
    }

    $scope.console = null;
    return false;
  };

  //set private methods
  function get(entity, id, callback) {
    blockUI.start("A obter dados...");
    getLookups($scope.lookup, function(err, lookups) {
      if (err) {
        inform.add("Não foi possível obter dados.", {ttl: 2000, type: 'danger'});
        blockUI.stop();
        callback(err);
        return;
      }

      $scope.lookup = lookups;

      //if user is creating a new record
      if (!$routeParams.id && $routeParams.action === 'edit') {
        blockUI.stop();
        callback();
        return;
      }

      $entity.get(entity, id)
      .then(function(response) {
        if (id) {
          $scope.item = response.data;
        }
        else {
          $scope.items = response.data;
          updateTable();
        }
      })
      .catch(function(response) {
        inform.add(response.error ? response.error : response.data, {ttl: 2000, type: 'danger'});
      })
      .finally(function() {
        blockUI.stop();
        callback();
      });
    });
  }

  function getLookups(lookup, callback) {
    if (lookup) {
      if (lookup.length) {
        callback(null, lookup);
        return;
      }
    }

    $entity.getLookups($routeParams.entity, function(err, data) {
      if (err) {
        callback(err);
        return;
      }

      callback(null, data);
    });
  }

  function setEdit(item) {
    if (item) {
      $scope.item = angular.copy(item);
    }
    else {
      $scope.item = typeof $scope.blank === 'function' ? $scope.blank() : {};
    }
  }

  function updateTable() {
    $scope.table.params = new NgTableParams({
      page: 1,
      count: $scope.items.length,
      sorting: {nome: "asc"}
    }, {
      total: 1,
      counts: [],
      dataset: $scope.items
    });
  }

  function loadFinished() {
    //inject child controller
    $controller($routeParams.entity + 'Ctrl', {$scope: $scope});

    mySocket.on($scope.login.owner + '.' + $routeParams.entity + '.remove', onThisEntityRemove);
    mySocket.on($scope.login.owner + '.' + $routeParams.entity + '.new', onThisEntityAdd);
    mySocket.on($scope.login.owner + '.' + $routeParams.entity + '.edit', onThisEntityEdit);
  }

  function onThisEntityAdd(data) {
    switch($routeParams.action) {
      case 'list':
        $scope.items.unshift(data);
        updateTable();
        break;
    }

    //todo update lookup
  }

  function onThisEntityEdit(data) {
    switch($routeParams.action) {
      case 'list':
        for (var i = 0; i < $scope.items.length; i++) {
          if ($scope.items[i]._id === data._id) {
            $scope.items[i] = data;
            updateTable();
            break;
          }
        }
        break;
      case 'view':
      case 'edit':
        if ($scope.item._id === data._id) {
          $scope.item = data;
        }
        break;
    }

    //todo update lookup
  }

  function onThisEntityRemove(data) {
    switch($routeParams.action) {
      case 'list':
        for (var i = 0; i < $scope.items.length; i++) {
          if ($scope.items[i]._id === data) {
            $scope.items.splice(i, 1);
            updateTable();
            break;
          }
        }
        break;

      case 'view':
      case 'edit':
        if ($scope.item._id === data._id) {
          $location.path('/' + $routeParams.entity + '/list');
        }
        break;
    }

    //todo update lookup
  }

  //initialization
  function initialize(callback) {
    $page.setTitle('Onde quer ir?');
    $scope.entity = entityMap[$routeParams.entity];
    if (!$scope.entity) {
      return;
    }

    switch ($routeParams.action) {
      case 'edit':
        if (!$routeParams.id) {
          $page.setTitle($scope.entity.title + ' - Novo Registo');
          get($routeParams.entity, null, callback);
        }
        else {
          $page.setTitle($scope.entity.title + ' - Alterar Registo');
          get($routeParams.entity, $routeParams.id, callback);
        }
        break;

      case 'view':
        if (!$routeParams.id) {
          return;
        }

        $page.setTitle($scope.entity.title + ' - Visualizar');
        get($routeParams.entity, $routeParams.id, callback);
        break;

      case 'list':
        if ($routeParams.id) {
          return;
        }

        $page.setTitle($scope.entity.title);
        get($routeParams.entity, null, callback);
        break;

      default:
        return;
    }
  }

  initialize(loadFinished);
});
