package com.ejie.aa94a.utils;

import java.math.BigDecimal;
import java.util.Iterator;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import com.ejie.aa94a.model.calculo.Bobina;
import com.ejie.aa94a.model.calculo.Mensaje;
import com.ejie.aa94a.model.calculo.Transporte;
import com.ejie.aa94a.model.config.Configuracion;
import com.ejie.aa94a.model.config.Solucion;
import com.ejie.aa94a.model.config.TipoSujecion;
import com.ejie.aa94a.model.config.Vehiculo;

/**
 * 
 * @author GFI-Norte
 * 
 */

public class UtilSolucion {

	private static final Logger logger = LoggerFactory
			.getLogger(UtilSolucion.class);

	private static final String COD_MENSAJE_SIN_SOLUCION = "1";

	private UtilSolucion() {
	}

	/**
	 * Comprueba si existe solución para la lista de bobinas. En caso de haber
	 * solución devuelve un objeto solución, y si no hay devuelve null.
	 * 
	 * @param transporte
	 *            Transporte
	 * @return Solucion
	 */
	public static Solucion obtenerSolucion(Transporte transporte) {
		UtilSolucion.logger.info("[obtenerSolucion - Inicio]");
		Solucion solucion = null;
		if (transporte != null && transporte.getBobinas() != null
				&& !transporte.getBobinas().isEmpty()) {
			List<Solucion> listaSoluciones = UtilSolucion.obtenerSoluciones(
					transporte.getVehiculo(), transporte.getTipoSujecion());
			if (listaSoluciones != null && !listaSoluciones.isEmpty()) {
				Iterator<Solucion> itSolucion = listaSoluciones.iterator();
				Solucion solucionAux = null;
				while (itSolucion.hasNext()) {
					solucionAux = itSolucion.next();
					if (UtilSolucion.compruebaSolucion(solucionAux,
							transporte.getBobinas())) {
						solucion = solucionAux;
						break;
					}
				}
			}
		}
		UtilSolucion.logger.info("[obtenerSolucion - Fin]");
		return solucion;
	}

	/**
	 * Obtiene el mensaje de sin solución
	 * 
	 * @return Mensaje
	 */
	public static Mensaje getMensajeSinSolucion() {
		List<Mensaje> listaMensajes = Configuracion.mensajes;
		Mensaje mensaje = null;
		if (listaMensajes != null && !listaMensajes.isEmpty()) {
			Mensaje mensajeAux = null;
			Iterator<Mensaje> itMensajes = listaMensajes.iterator();
			while (itMensajes.hasNext()) {
				mensajeAux = itMensajes.next();
				if (Integer.valueOf(UtilSolucion.COD_MENSAJE_SIN_SOLUCION)
						.equals(mensajeAux.getCodigo())) {
					mensaje = mensajeAux;
					break;
				}

			}

		}
		return mensaje;
	}

	/**
	 * Comprueba si la lista de bobinas cumple alguna de las soluciones
	 * 
	 * @param solucion
	 * @param listaBobinas
	 * @return boolean
	 */
	private static boolean compruebaSolucion(Solucion solucion,
			List<Bobina> listaBobinas) {
		boolean resultado = false;
		if (solucion != null) {
			int numBobinas = listaBobinas.size();
			if (numBobinas == solucion.getNumBobinas().intValue()) {
				List<String> condiciones = solucion.getCondiciones();
				if (condiciones != null && !condiciones.isEmpty()) {
					resultado = true;
					Iterator<String> itCondiciones = condiciones.iterator();
					String condicion = null;
					while (itCondiciones.hasNext()) {
						condicion = itCondiciones.next();
						if (!StringUtils.trimAllWhitespace(condicion)
								.equals("")) {
							resultado = UtilSolucion.compruebaCondicion(
									condicion, listaBobinas);
						}
						if (!resultado) {
							break;
						}
					}
				}
			}
		}
		return resultado;
	}

	/**
	 * Funcion que sustituye la cadena 'from' por 'to' en una cadena 'repString'
	 * 
	 * @param from
	 *            String
	 * @param to
	 *            String
	 * @param repString
	 *            String
	 * @return String
	 */
	public static String strReplace(String texto, String parametroRemplace,
			String parametroPoner) {

		String textoReemplazado = texto.replace(parametroRemplace,
				parametroPoner);
		return textoReemplazado;
	}

	/**
	 * 
	 * @param condicion
	 *            String
	 * @param listaBobinas
	 *            List<Bobina>
	 * @return String
	 */
	private static String reemplazaCondicionesPesosBobinas(String condicion,
			List<Bobina> listaBobinas) {
		String resultado = new StringBuffer(condicion).toString();
		if (listaBobinas != null && !listaBobinas.isEmpty()) {
			Iterator<Bobina> itBobinas = listaBobinas.iterator();
			Bobina bobina = null;
			int pos = 0;
			String VAR_ANCHO = "WIDTH_";
			while (itBobinas.hasNext()) {
				bobina = itBobinas.next();
				// SUSTITUYE ANCHURA
				if (condicion.indexOf(VAR_ANCHO) != -1) {
					resultado = UtilSolucion
							.strReplace(
									resultado,
									new StringBuffer(VAR_ANCHO).append(
											UtilConfiguracion
													.getIdentificador(pos))
											.toString(), bobina.getAnchura()
											.toString());
					// SUSTITUYE PESO
				} else {
					resultado = UtilSolucion.strReplace(resultado,
							UtilConfiguracion.getIdentificador(pos), bobina
									.getPeso().toString());
				}
				pos++;
			}
		}
		return resultado;
	}

	private static boolean compruebaCondicion(String condicion,
			List<Bobina> listaBobinas) {
		boolean validaCondicion = false;
		final int COND_CORRECTA = 1;
		if (condicion != null) {
			BigDecimal result = null;
			Expression expression = new Expression(
					UtilSolucion.reemplazaCondicionesPesosBobinas(condicion,
							listaBobinas));
			result = expression.eval();
			// 0 no cumple
			// 1 cumple condicion
			if (result.intValue() == COND_CORRECTA) {
				validaCondicion = true;
			}
		}
		return validaCondicion;
	}

	/*
	 * public static void main(String[] args) { boolean condicion =
	 * UtilSolucion.compruebaCondicion(" A S F; ", null); if (condicion) {
	 * condicion = false; }
	 * 
	 * }
	 */

	/**
	 * Obtiene la lista de soluciones configurada para el tipo de vehiculo y el
	 * tipo de sujecion.
	 * 
	 * @param vehiculo
	 * @param tipoSujecion
	 * @return
	 */
	private static List<Solucion> obtenerSoluciones(Vehiculo vehiculo,
			TipoSujecion tipoSujecion) {
		UtilSolucion.logger.info("[obtenerSoluciones - Inicio]");
		List<Solucion> listaSoluciones = null;
		if (vehiculo != null && tipoSujecion != null
				&& vehiculo.getCodigo() != null
				&& tipoSujecion.getCodigo() != null) {
			List<Vehiculo> listaVehiculos = Configuracion.soluciones;
			if (listaVehiculos != null && !listaVehiculos.isEmpty()) {
				Iterator<Vehiculo> itVehiculos = listaVehiculos.iterator();
				while (itVehiculos.hasNext()) {
					Vehiculo vehiculoAux = itVehiculos.next();
					if (vehiculo.getCodigo().intValue() == vehiculoAux
							.getCodigo().intValue()) {
						List<TipoSujecion> listaTiposSujecion = vehiculoAux
								.getTiposSujecion();
						if (listaTiposSujecion != null
								&& !listaTiposSujecion.isEmpty()) {
							Iterator<TipoSujecion> itTiposSujecion = listaTiposSujecion
									.iterator();
							while (itTiposSujecion.hasNext()) {
								TipoSujecion tipoSujecionAux = itTiposSujecion
										.next();
								if (tipoSujecion.getCodigo().intValue() == tipoSujecionAux
										.getCodigo().intValue()) {
									listaSoluciones = tipoSujecionAux
											.getSoluciones();
									break;
								}
							}
						}

					}
				}
			}
		}
		UtilSolucion.logger.info("[obtenerSoluciones - Fin]");
		return listaSoluciones;
	}
}