/**
 * Obtiene los contactos que se encuentran registrados en el sistemas y estan conectados,
 * a partir de numeros de telefono que recibe
 *
 */
void Servicio::obtenerContactos() {
	Json::Value contactosTelefonoValue = this->getParametroArray(
	keyContantosTelefono, keyDefault);
	vector<string> contactosTelefono = StringUtil::jsonValueToVector(
			contactosTelefonoValue);

	Json::Value respuesta;
	int counter = 0;
	for (unsigned i = 0; i < contactosTelefono.size(); i++) {
		string telefonoActual = contactosTelefono[i];
		Usuario* usuario = Usuario::obtenerPorTelefono(telefonoActual);

		//Agrego los usuarios que estan registrados y que se encuentran conectados

		if (usuario->getId() != keyIdUsuarioNoEncontrado
				&& usuario->getEstadoConexion()) {
			respuesta["contactos"][counter][keyNombre] = usuario->getNombre();
			respuesta["contactos"][counter][keyTelefono] =
					usuario->getTelefono();
			respuesta["contactos"][counter][keyFotoDePerfil] =
					usuario->getFotoDePerfil();
			respuesta["contactos"][counter][keyLocalizacion] = usuario->getLocalizacion();
			counter++;
		}
	}

	this->responder(respuesta.toStyledString(), true);
}
/**
 * Devuelve los datos correspondientes al usuario con telefono igual al
 * recibido.
 */
void Servicio::consultarUsuarioOnline() {
	string telefono = this->getParametroIdMetodoGET(urlBaseUsuario);
	Usuario* user = Usuario::obtenerPorTelefono(telefono);

	string renovarToken = this->getParametro(keyRenovarToken, keyDefault);
	bool renovar = StringUtil::toBoolean(renovarToken);

	if (user->getId() != keyIdUsuarioNoEncontrado) {
		user->registrarUltimaConexion();

		Json::Value respuesta;
		respuesta[keyNombre] = user->getNombre();
		respuesta[keyPassword] = user->getPassword();
		if(renovar){
			respuesta[keyTokenSesion] = user->calcularTokenDeSesion();
		}else{
			respuesta[keyTokenSesion] = user->getToken();
		}
		respuesta[keyEstadoDeConexion] = StringUtil::toString(
				user->getEstadoConexion());
		respuesta[keyFotoDePerfil] = user->getFotoDePerfil();
		respuesta["idUsuario"] = user->getId();
		respuesta[keyLocalizacion] = user->getLocalizacion();
		user->persistir();

		this->responder(respuesta.toStyledString(), true);
		Loger::getLoger()->info(
				"Consulta del usuario " + user->getNombre() + " exitosa.");

	} else {
		string msj = "No se pudo obtener el estado del usuario con numero: "
				+ this->getParametro(keyTelefono, keyDefault)
				+ " ya que no se encuentra registrado en el sistema.";

		Loger::getLoger()->warn(msj);
		this->responder(msj, false);
	}

	Loger::getLoger()->guardarEstado();
	delete user;

}
void TestConversacion::testSerializacionDeDatosUnaConversacion() {
	Usuario* user = new Usuario("Pepe", "foto", "1568017070");
	Usuario* user2 = new Usuario("Jose", "foto2", "156801515");

	BaseDeDatos* db = BaseDeDatos::getInstance();
	db->setUsuario(user);
	db->setUsuario(user2);

	vector<Usuario*> usuarios;
	usuarios.push_back(user);
	usuarios.push_back(user2);

	vector<Mensaje*> mensajes;
	mensajes.push_back(new Mensaje("cuerpo mensaje 1", "asdasd", "fecha1"));
	mensajes.push_back(new Mensaje("cuerpo mensaje 2", "asdasd2", "fecha2"));

	Conversacion* conversacion = new Conversacion(usuarios, mensajes);
	string conversacionSerializada = conversacion->serializar();

	Conversacion* conv2 = new Conversacion(conversacionSerializada);
	vector<Mensaje*> mensajesDeserealizados = conv2->getMensajes();

	vector<Usuario*> usuariosDeserealizados = conv2->getUsuarios();

	CPPUNIT_ASSERT(
			mensajes[0]->getCuerpo() == mensajesDeserealizados[0]->getCuerpo());
	CPPUNIT_ASSERT(
			mensajes[1]->getCuerpo() == mensajesDeserealizados[1]->getCuerpo());
	CPPUNIT_ASSERT(
			mensajes[0]->getIdUsuarioEmisor()
					== mensajesDeserealizados[0]->getIdUsuarioEmisor());
	CPPUNIT_ASSERT(
			mensajes[1]->getIdUsuarioEmisor()
					== mensajesDeserealizados[1]->getIdUsuarioEmisor());
	CPPUNIT_ASSERT(
			mensajes[0]->getFecha() == mensajesDeserealizados[0]->getFecha());
	CPPUNIT_ASSERT(
			mensajes[1]->getFecha() == mensajesDeserealizados[1]->getFecha());

	CPPUNIT_ASSERT(user->getNombre() == usuariosDeserealizados[0]->getNombre());
	CPPUNIT_ASSERT(user->getId() == usuariosDeserealizados[0]->getId());

	CPPUNIT_ASSERT(
			user2->getNombre() == usuariosDeserealizados[1]->getNombre());
	CPPUNIT_ASSERT(user2->getId() == usuariosDeserealizados[1]->getId());

	delete user;
	delete user2;
	delete conversacion;
	delete conv2;

}
/**
 * Registra un usuario en el sistema
 *
 */
void Servicio::registrarUsuario() {

	Usuario* user = this->obtenerUsuario();
	if (user->getId() != keyIdUsuarioNoEncontrado) {
		//El usuario ya existe. Devuelvo error
		Loger::getLoger()->warn(
				"Se intento registrar un usuario ya existente. Id: "
						+ user->getId());
		this->responder("El usuario ya existe", false);
	} else {
		string nombre = this->getParametro(keyNombre, keyDefault);
		string fotoPerfil = this->getParametro(keyFotoDePerfil, keyDefault);
		string telefono = this->getParametro(keyTelefono, keyDefault);
		string password = this->getParametro(keyPassword, keyDefault);

		Usuario* user = new Usuario(nombre, telefono, password);

		user->persistir();
		this->responder("Usuario registrado correctamente", true);
		Loger::getLoger()->info(
				"Se registro el usuario con Id: " + user->getId());
		delete user;
	}
}
/**
 * Se encarga de actualizar los datos del usuario que recibe, en la
 * base de datos.
 */
void Servicio::administrarPerfil() {

	string nombreUsuario = this->getParametro(keyNombre, keyDefault);
	string estadoDeConexion = this->getParametro(keyEstadoDeConexion,
			keyDefault);
	string fotoDePerfil = this->getParametro(keyFotoDePerfil, keyDefault);
	bool estado = StringUtil::toBoolean(estadoDeConexion);
	string localizacion = this->getParametro(keyLocalizacion, keyDefault);
	string password = this->getParametro(keyPassword, keyDefault);
	Usuario* user = this->obtenerUsuario();
	string token = this->getParametro(keyTokenSesion, keyDefault);

	if (user->getId() != keyIdUsuarioNoEncontrado) {
		if (user->getToken() == token) {
			user->setNombre(nombreUsuario);
			user->setEstadoConexion(estado);
			user->setFotoDePerfil(fotoDePerfil);
			user->setLocalizacion(localizacion);
			user->setPassword(password);
			user->persistir();
			Loger::getLoger()->info(
					"Se modificaron los datos del usuario " + user->getNombre()
							+ " correctamente.");
			this->responder(
					"Se modificaron los datos del usuario " + user->getNombre()
							+ " correctamente. Token:" + user->getToken(),
					true);
		} else {
			Loger::getLoger()->warn(
					"El usuario " + user->getNombre()
							+ " no posee un token de session correcto");
			this->responder(
					"El usuario " + user->getNombre()
							+ " no posee un token de session correcto", false);
		}

	} else {
		Loger::getLoger()->warn(
				"El usuario " + user->getNombre()
						+ " no se encuentra registrado en el sistema");
		this->responder(
				"El usuario " + user->getNombre()
						+ " no se encuentra registrado en el sistema", false);
	}
	Loger::getLoger()->guardarEstado();
	delete user;

}
/**
 * Devuelve el id de una conversacion a partir de dos telefonos
 *
 */
void Servicio::obtenerIdConversacion() {
	string telefonoUsuarioEmisor = this->getParametro(keyTelefonoEmisor,
			keyDefault);
	;
	string telefonoUsuarioRecceptor = this->getParametro(keyTelefonoReceptor,
			keyDefault);

	Usuario* usuarioEmisor = Usuario::obtenerPorTelefono(telefonoUsuarioEmisor);
	Usuario* usuarioReceptor = Usuario::obtenerPorTelefono(
			telefonoUsuarioRecceptor);

	if (usuarioEmisor->getId() != keyIdUsuarioNoEncontrado
			&& usuarioReceptor->getId() != keyIdUsuarioNoEncontrado) {
		vector<Mensaje*> mensajes;
		vector<Usuario*> usuarios;
		usuarios.push_back(usuarioEmisor);
		usuarios.push_back(usuarioReceptor);
		Conversacion *conversacion = Conversacion::obtener(
				usuarioEmisor->getId() + "-" + usuarioReceptor->getId());
		if (conversacion->getId() == keyIdConversacionNoEncontrada) {
			conversacion = Conversacion::obtener(
					usuarioReceptor->getId() + "-" + usuarioEmisor->getId());
		}
		string idConversacion = conversacion->getId();
		if (idConversacion != keyIdUsuarioNoEncontrado) {
			this->responder(idConversacion, true);
		} else {
			//Si la conversacion no existe devuelvo como id uno default para estos dos usuarios
			Conversacion* conversacion = new Conversacion(usuarios, mensajes);
			string idConversacion = conversacion->getId();

			this->responder(idConversacion, false);
		}
	} else {
		Usuario* user;
		if (usuarioEmisor->getId() == keyIdUsuarioNoEncontrado) {
			user = usuarioEmisor;
		} else {
			user = usuarioReceptor;
		}
		string msj_warn = "Usuario " + user->getNombre()
				+ " no se encuentra registrado en el sistema";

		Loger::getLoger()->warn(msj_warn);
		this->responder(msj_warn, false);
	}

	delete usuarioEmisor;
	delete usuarioReceptor;
}
/**
 * Se encarga de calcular en que lugar se encuentra el cliente
 * en base a sus coordenadas geográficas y los lugares precargados.
 *
 */
void Servicio::checkIn() {
	Json::Value coordenadas;
	string latitud = this->getParametro(keyLatitud, keyDefault);
	string longitud = this->getParametro(keyLongitud, keyDefault);
	coordenadas["latitud"] = atof(latitud.c_str());
	coordenadas["longitud"] = atof(longitud.c_str());

	Usuario* usuario = this->obtenerUsuario();
	if (usuario->getId() != keyIdUsuarioNoEncontrado) {
		string localizacion = Localizacion::calcularUbicacion(coordenadas)+" "+fechaYhoraActual();
		usuario->setLocalizacion(localizacion);
		usuario->persistir();
		this->responder(localizacion, true);
	} else {
		this->responder("el usuario no existe.", false);
	}
}
/*
 * Agrega el mensaje que envió el cliente a la conversacion correspondiente y luego la almacena en
 * la Base de Datos.
 *
 */
void Servicio::almacenarListaDifusion() {
	string idEmisor = this->getParametro(keyIdUsuarioEmisor, keyDefault);
	string token = this->getParametro(keyTokenSesion, keyDefault);

	Json::Value contactosTelefonoValue = this->getParametroArray(
	keyContantosTelefono, keyDefault);
	vector<string> contactosTelefono = StringUtil::jsonValueToVector(
			contactosTelefonoValue);

//chequeo que los usuarios existan:
	Usuario *emisor = Usuario::obtenerPorTelefono(idEmisor);

	if (emisor->getId() == keyIdUsuarioNoEncontrado) {
		string msj_warning =
				"No se pudo almacenar la lista de difusion porque el emisor no existe";
		this->responder(msj_warning, false);
		Loger::getLoger()->warn(msj_warning);
		Loger::getLoger()->guardarEstado();
	} else if (emisor->getToken() != token) {
		Loger::getLoger()->warn(
				"El usuario " + emisor->getNombre()
						+ " no posee un token de session correcto");
		this->responder(
				"El usuario " + emisor->getNombre()
						+ " no posee un token de session correcto", false);
	} else {
		//Obtengo el mensaje:
		string cuerpo = this->getParametro(keyCuerpo, keyDefault);
		string fecha = this->getParametro(keyFecha, keyDefault);
		Mensaje* mensaje = new Mensaje(cuerpo, emisor->getId(), fecha);

		//Recorro los contactos del telefono para verificar cuales estan registrados y conectados
		for (unsigned i = 0; i < contactosTelefono.size(); i++) {
			string telefonoActual = contactosTelefono[i];
			Usuario* usuario = Usuario::obtenerPorTelefono(telefonoActual);

			//Envío mensaje a los usuarios que estan registrados y que se encuentran conectados
			if (usuario->getId() != keyIdUsuarioNoEncontrado
					&& usuario->getEstadoConexion()) {
				//almaceno la conversacion (si no existe la creo):
				Conversacion *conversacion = Conversacion::obtener(
						emisor->getId() + "-" + usuario->getId());
				if (conversacion->getId() != keyIdConversacionNoEncontrada) {
					conversacion->agregarMensaje(mensaje);
					conversacion->persistir();
					delete conversacion;
				} else {
					Conversacion *conversacion = Conversacion::obtener(
							usuario->getId() + "-" + emisor->getId());
					if (conversacion->getId()
							!= keyIdConversacionNoEncontrada) {
						conversacion->agregarMensaje(mensaje);
						conversacion->persistir();
						delete conversacion;
					} else {
						vector<Usuario*> usuarios;
						usuarios.push_back(emisor);
						usuarios.push_back(usuario);
						vector<Mensaje*> mensajes;
						mensajes.push_back(mensaje);
						Conversacion *nuevaConversacion = new Conversacion(
								usuarios, mensajes);
						nuevaConversacion->persistir();
						delete nuevaConversacion;
					}
				}
			}
		}

		this->responder("Lista de difusion enviada correctamente", true);
		delete mensaje;
	}
}
void Servicio::obtenerConversaciones() {
	Json::Value idsConversacionesValue = this->getParametroArray(
	keyIdConversaciones, keyDefault);
	vector<string> idsConversaciones = StringUtil::jsonValueToVector(
			idsConversacionesValue);

	string idUsuario = this->getParametroIdMetodoGET(
			urlBaseUsuarioConversaciones);

	Usuario* usuario = Usuario::obtenerPorTelefono(idUsuario);
	if (usuario->getId() != keyIdUsuarioNoEncontrado) {
		vector<string> idsConversacionesActuales =
				usuario->obtnerIdsConversaciones();
		vector<Conversacion*> nuevasConversaciones;

		for (unsigned i = 0; i < idsConversacionesActuales.size(); i++) {
			string idActual = idsConversacionesActuales[i];

			//Si no esta en las conversaciones que me llegan, quiere decir que es una nueva conversacion.
			//Tengo que enviarla al cliente
			if (!StringUtil::vectorContiene(idsConversaciones, idActual)) {
				Conversacion* nuevaConversacion = Conversacion::obtener(
						idActual);
				if (nuevaConversacion->getId()
						!= keyIdConversacionNoEncontrada) {
					nuevasConversaciones.push_back(nuevaConversacion);
				} else {
					Loger::getLoger()->warn(
							"La conversacion " + idActual
									+ " no se encuentra en el sistema");
				}
			}
		}

		Json::Value respuesta;

		for (unsigned i = 0; i < nuevasConversaciones.size(); i++) {
			Conversacion* conv = nuevasConversaciones[i];

			vector<Mensaje*> mens = conv->getMensajes();
			Mensaje* ultimoMensj = mens[mens.size() - 1];

			Usuario* usuarioContacto = conv->getUsuarios().at(0);
			if (usuarioContacto->getId() == usuario->getId()) {
				usuarioContacto = conv->getUsuarios().at(1);
			}

			respuesta["conversaciones"][i]["id"] = conv->getId();
			respuesta["conversaciones"][i]["ultimoMensaje"] =
					ultimoMensj->getCuerpo();
			respuesta["conversaciones"][i]["usuarioNombre"] =
					usuarioContacto->getNombre();
			respuesta["conversaciones"][i]["usuarioTelefono"] =
					usuarioContacto->getTelefono();
			respuesta["conversaciones"][i]["usuarioFotoDePerfil"] =
					usuarioContacto->getFotoDePerfil();

		}

		this->responder(respuesta.toStyledString(), true);

	} else {
		Loger::getLoger()->warn(
				"El usuario " + idUsuario + " no se encuentra en el sistema");
	}

}
/*
 * Agrega el mensaje que envió el cliente a la conversacion correspondiente y luego la almacena en
 * la Base de Datos.
 *
 */
void Servicio::almacenarConversacion() {

	string idEmisor = this->getParametro(keyIdUsuarioEmisor, keyDefault);
	string idReceptor = this->getParametro(keyIdUsuarioReceptor, keyDefault);

	//chequeo que los usuarios existan:
	Usuario *emisor = Usuario::obtenerPorTelefono(idEmisor);
	Usuario *receptor = Usuario::obtenerPorTelefono(idReceptor);

	string token = this->getParametro(keyTokenSesion, keyDefault);

	if (emisor->getId() == keyIdUsuarioNoEncontrado
			|| receptor->getId() == keyIdUsuarioNoEncontrado) {
		string msj_warning = "No se pudo almacenar la conversacion porque: ";
		if (emisor->getId() == keyIdUsuarioNoEncontrado)
			msj_warning.append("el emisor no existe.");
		if (receptor->getId() == keyIdUsuarioNoEncontrado)
			msj_warning.append(" el receptor no existe.");
		this->responder(msj_warning, false);
		Loger::getLoger()->warn(msj_warning);
		Loger::getLoger()->guardarEstado();

	} else {
		if (emisor->getToken() == token) {
			//Obtengo el mensaje:
			string cuerpo = this->getParametro(keyCuerpo, keyDefault);
			string fecha = this->getParametro(keyFecha, keyDefault);
			Mensaje* mensaje = new Mensaje(cuerpo, emisor->getId(), fecha);

			//almaceno la conversacion (si no existe la creo):
			Conversacion *conversacion = Conversacion::obtener(
					emisor->getId() + "-" + receptor->getId());
			if (conversacion->getId() != keyIdConversacionNoEncontrada) {
				conversacion->agregarMensaje(mensaje);
				conversacion->persistir();
				delete conversacion;
			} else {
				Conversacion *conversacion = Conversacion::obtener(
						receptor->getId() + "-" + emisor->getId());
				if (conversacion->getId() != keyIdConversacionNoEncontrada) {
					conversacion->agregarMensaje(mensaje);
					conversacion->persistir();
					delete conversacion;
				} else {
					vector<Usuario*> usuarios;
					usuarios.push_back(emisor);
					usuarios.push_back(receptor);
					vector<Mensaje*> mensajes;
					mensajes.push_back(mensaje);
					Conversacion *nuevaConversacion = new Conversacion(usuarios,
							mensajes);
					nuevaConversacion->persistir();
					delete nuevaConversacion;
				}
			}

			this->responder(mensaje->getId(), true);
			delete mensaje;
		} else {
			string msj = "El usuario " + emisor->getNombre()
					+ " no posee un token de session correcto";
			Loger::getLoger()->warn(msj);
			this->responder(msj, false);
		}
	}

}