'use strict';

	/**
	 * Le controller permet l'interaction entre {@link Model} et {@Link View}.
	 * @constructor
	 * @param {object} (model) L'instance {@link Model}.
	 * @param {object} (view) L'instance {@Link View}.
	 */
	function Controller(model, view) {
		var self = this;
		self.model = model;
		self.view = view;

		self.view.bind('newTodo', function (title) {
			self.addItem(title);
		});

		self.view.bind('itemEdit', function (item) {
			self.editItem(item.id);
		});

		self.view.bind('itemEditDone', function (item) {
			self.editItemSave(item.id, item.title);
		});

		self.view.bind('itemEditCancel', function (item) {
			self.editItemCancel(item.id);
		});

		self.view.bind('itemRemove', function (item) {
			self.removeItem(item.id);
		});

		self.view.bind('itemToggle', function (item) {
			self.toggleComplete(item.id, item.completed);
		});

		self.view.bind('removeCompleted', function () {
			self.removeCompletedItems();
		});

		self.view.bind('toggleAll', function (status) {
			self.toggleAll(status.completed);
		});
	}


	/**
	 * Initialise la vue {@link View}.
	 * @param {string} (locationHash) Le hash de la page en cours, peut avoir les valeurs :
	 *                                 '' | 'active' | 'completed' .
	 */
	Controller.prototype.setView = function (locationHash) {
		var route = locationHash.split('/')[1];
		var page = route || '';
		this._updateFilterState(page);
	};


	/**
	 * Affiche tous les todos dans la liste.
	 */
	Controller.prototype.showAll = function () {
		var self = this;
		self.model.read(function (data) {
			self.view.render('showEntries', data);
		});
	};


	/**
	 * Retourne tous les ToDos actifs - completed: false.
	 */
	Controller.prototype.showActive = function () {
		var self = this;
		self.model.read({ completed: false }, function (data) {
			self.view.render('showEntries', data);
		});
	};


	/**
	 * Retourne tous les ToDos complétés - completed: true.
	 */
	Controller.prototype.showCompleted = function () {
		var self = this;
		self.model.read({ completed: true }, function (data) {
			self.view.render('showEntries', data);
		});
	};


	/**
	 * Ajoute un nouveau ToDo.
	 * @param {string} (title) Le contenu du todo.
	 */
	Controller.prototype.addItem = function (title) {
		var self = this;

		if (title.trim() === '') {
			return;
		}

		self.model.create(title, function () {
			self.view.render('clearNewTodo');
			self._filter(true);
		});
	};


	/*
	 * Permet de modifier un ToDo.
	 * @param {number} (id) L'ID du model à éditer.
	 */
	Controller.prototype.editItem = function (id) {
		var self = this;
		self.model.read(id, function (data) {
			self.view.render('editItem', {id: id, title: data[0].title});
		});
	};


	/*
	 * Enregistre la modification d'un ToDo.
	 * @param {number} (id) L'ID du model à sauvegarder.
	 * @param {string} (title) Le contenu du todo.
	 */
	Controller.prototype.editItemSave = function (id, title) {
		var self = this;

		while (title[0] === " ") {
			title = title.slice(1);
		}

		while (title[title.length-1] === " ") {
			title = title.slice(0, -1);
		}

		if (title.length !== 0) {
			self.model.update(id, {title: title}, function () {
				self.view.render('editItemDone', {id: id, title: title});
			});
		} else {
			self.removeItem(id);
		}
		console.log("Element with ID: " + id + " has been edit.");
	};


	/*
	 * Annule la modification d'un ToDo.
	 * @param {number} (id) L'ID du model.
	 */
	Controller.prototype.editItemCancel = function (id) {
		var self = this;
		self.model.read(id, function (data) {
			self.view.render('editItemDone', {id: id, title: data[0].title});
		});
	};


	/**
	 * Supprime un ToDo.
	 * @param {number} (id) L'ID du ToDo à supprimer.
	 */
	Controller.prototype.removeItem = function (id) {
		var self = this;
		var items;
		self.model.read(function(data) {
			items = data;
		});

		self.model.remove(id, function () {
			self.view.render('removeItem', id);
			console.log("Element with ID: " + id + " has been removed.");
		});

		self._filter();
	};


	/**
	 * Supprime tous les ToDos complétés.
	 */
	Controller.prototype.removeCompletedItems = function () {
		var self = this;
		self.model.read({ completed: true }, function (data) {
			data.forEach(function (item) {
				self.removeItem(item.id);
			});
		});

		self._filter();
	};


	/**
	 * Change le statut d'un ToDo
	 * @param {number} (id) L'ID du ToDo.
	 * @param {object} (checkbox) La checkbox.
	 * @param {boolean|undefined} (silent) Empêche le re-filtrage des ToDos.
	 */
	Controller.prototype.toggleComplete = function (id, completed, silent) {
		var self = this;
		self.model.update(id, { completed: completed }, function () {
			self.view.render('elementComplete', {
				id: id,
				completed: completed
			});
		});

		if (!silent) {
			self._filter();
		}
	};


	/**
	 * Change le statut de tous les ToDos
	 * @param {object} (checkbox) La checkbox.
	 */
	Controller.prototype.toggleAll = function (completed) {
		var self = this;
		self.model.read({ completed: !completed }, function (data) {
			data.forEach(function (item) {
				self.toggleComplete(item.id, completed, true);
			});
		});

		self._filter();
	};


	/**
	 * Met à jour le nombre de ToDos.
	 */
	Controller.prototype._updateCount = function () {
		var self = this;
		self.model.getCount(function (todos) {
			self.view.render('updateElementCount', todos.active);
			self.view.render('clearCompletedButton', {
				completed: todos.completed,
				visible: todos.completed > 0
			});

			self.view.render('toggleAll', {checked: todos.completed === todos.total});
			self.view.render('contentBlockVisibility', {visible: todos.total > 0});
		});
	};


	/**
	 * Filtre les ToDos en fonction de leur statut et de la route.
	 * @param {boolean|undefined} (force)  Refiltre les ToDos.
	 */
	Controller.prototype._filter = function (force) {
		var activeRoute = this._activeRoute.charAt(0).toUpperCase() + this._activeRoute.substr(1);

		this._updateCount();

		if (force || this._lastActiveRoute !== 'All' || this._lastActiveRoute !== activeRoute) {
			this['show' + activeRoute]();
		}

		this._lastActiveRoute = activeRoute;
	};


	/**
	 * Met à jour le statut coché selon la route.
	 * @param  {string} (currentPage) La route de la page actuelle '' || active || completed.
	 */
	Controller.prototype._updateFilterState = function (currentPage) {

		this._activeRoute = currentPage;

		if (currentPage === '') {
			this._activeRoute = 'All';
		}

		this._filter();

		this.view.render('setFilter', currentPage);
	};

	window.app = window.app || {};
	window.app.Controller = Controller;