package com.fp.frontend.webservices.impl;

import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.jws.WebService;
import javax.xml.bind.JAXBException;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.StringUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;

import com.fp.alfresco.client.AlfrescoApi;
import com.fp.common.logger.APPLogger;
import com.fp.dto.Request;
import com.fp.dto.Response;
import com.fp.frontend.helper.CallerHelper;
import com.fp.frontend.webservices.DatosSnapService;
import com.fp.frontend.webservices.snap.modelo.CabeceraXml;
import com.fp.frontend.webservices.snap.modelo.DatosArmaXml;
import com.fp.frontend.webservices.snap.modelo.EjecucionXml;
import com.fp.frontend.webservices.snap.modelo.GuardiaXml;
import com.fp.frontend.webservices.snap.modelo.ImagenXml;
import com.fp.frontend.webservices.snap.modelo.ResultadoXml;
import com.fp.frontend.webservices.snap.modelo.SoapEnvelopWrapper;
import com.fp.frontend.webservices.snap.modelo.TramiteXml;
import com.fp.persistence.parmas.dto.ws.DatosArmaDto;
import com.fp.persistence.parmas.dto.ws.DatosSnapDto;
import com.fp.persistence.parmas.dto.ws.InfoGuardiaDto;
import com.fp.persistence.parmas.dto.ws.TramiteDto;

/**
 * Web Service para poner a disposición la información de armas
 *
 * @author Manuel Cepeda
 *
 */
@WebService(endpointInterface = "com.fp.frontend.webservices.DatosSnapService")
public class DatosSnapServiceImpl implements DatosSnapService {

    /**
     * Implementacion del metodo que permite obtener la informacion de armas a
     * ser publicada
     *
     * @param institucion
     * @param nroDocumento
     * @param serie
     */
    @Override
    public SoapEnvelopWrapper obtenerDatos(String institucion, String nroDocumento, String serie) throws JAXBException {

        SimpleDateFormat formatoFecha = new SimpleDateFormat("dd/MM/yyyy");
        SimpleDateFormat formatoHora = new SimpleDateFormat("HH:mm:ss");
        if ("EXITO".equals(verificarDatos(institucion, nroDocumento, serie))) {
            CabeceraXml cabeceraXml = new CabeceraXml("XC001", formatoFecha.format(new Date()), formatoHora.format(new Date()));

            if (institucion.equals(InstitucionSnapEnum.MINISTERIO_MINAS.getNombre())) {
                DatosSnapDto personaSnapDto = obtenerPersonDetail(nroDocumento, institucion, serie);
                if (personaSnapDto != null) {
                    ResultadoXml resultadoXml = new ResultadoXml(personaSnapDto.getRazonSocial(), personaSnapDto.getDireccion(), personaSnapDto.getEmail(), personaSnapDto.getTelefonoFijo(), personaSnapDto.getTelefonoCelular());
                    List<TramiteXml> listaTramites = new ArrayList<>();
                    for (TramiteDto tramiteDto : personaSnapDto.getListaTramites()) {
                        TramiteXml tramiteXml = new TramiteXml(formatoFecha.format(tramiteDto.getFechaEmision()), formatoFecha.format(tramiteDto.getFechaExpiracion()), tramiteDto.getNumeroDocumento());
                        listaTramites.add(tramiteXml);
                    }
                    resultadoXml.setListaTramites(listaTramites);

                    EjecucionXml ejecucionXml = new EjecucionXml(1, "", "", "12345678");
                    SoapEnvelopWrapper soap = new SoapEnvelopWrapper(cabeceraXml, ejecucionXml, resultadoXml);
                    return soap;
                } else {
                    return null;
                }

            } else if (institucion.equals(InstitucionSnapEnum.CRIMINALISTICA.getNombre()) || institucion.equals(InstitucionSnapEnum.COPS.getNombre()) || institucion.equals(InstitucionSnapEnum.FISCALIA_GENERAL.getNombre())) {
                DatosSnapDto personaSnapDto = obtenerPersonDetail(nroDocumento, institucion, serie);
                if (personaSnapDto != null) {
                    ResultadoXml resultadoXml = new ResultadoXml(personaSnapDto.getRazonSocial(), personaSnapDto.getDireccion(), personaSnapDto.getEmail(), personaSnapDto.getTelefonoFijo(), personaSnapDto.getTelefonoCelular());
                    String xPathLocation = personaSnapDto.getxPathLocation();
                    if (institucion.equals(InstitucionSnapEnum.COPS.getNombre())) {
                        if (personaSnapDto.getTestPsicologico() != null && !"".equals(personaSnapDto.getTestPsicologico())) {
                            resultadoXml.setTestPsicologico(new ImagenXml(parseToString(xPathLocation + personaSnapDto.getTestPsicologico()), "TestPsicologico", FilenameUtils.getExtension(personaSnapDto.getTestPsicologico())));
                        }
                    }

                    List<TramiteXml> listaTramites = new ArrayList<>();
                    for (TramiteDto tramiteDto : personaSnapDto.getListaTramites()) {
                        TramiteXml tramiteXml = new TramiteXml(formatoFecha.format(tramiteDto.getFechaEmision()), formatoFecha.format(tramiteDto.getFechaExpiracion()), tramiteDto.getNumeroDocumento());
                        listaTramites.add(tramiteXml);
                    }
                    resultadoXml.setListaTramites(listaTramites);

                    List<GuardiaXml> listaGuardias = new ArrayList<>();
                    if (personaSnapDto.getListaGuardias() != null && !personaSnapDto.getListaGuardias().isEmpty()) {
                        for (InfoGuardiaDto infoGuardiaDto : personaSnapDto.getListaGuardias()) {
                            GuardiaXml guardiaXml = new GuardiaXml(infoGuardiaDto.getNombre(), infoGuardiaDto.getEmpresa(), infoGuardiaDto.getEstado());
                            listaGuardias.add(guardiaXml);
                        }
                        resultadoXml.setListaGuardias(listaGuardias);
                    }

                    try {
                        if (personaSnapDto.getListaDatosArma() != null && !personaSnapDto.getListaDatosArma().isEmpty()) {
                            List<DatosArmaXml> listaDatosArmaXml = new ArrayList<>();
                            for (DatosArmaDto datosArmaDto : personaSnapDto.getListaDatosArma()) {
                                DatosArmaXml datosArmaXml = new DatosArmaXml();

                                datosArmaXml.setLote(datosArmaDto.getLote());
                                datosArmaXml.setDescripcionClase(datosArmaDto.getDescripcionClase());
                                datosArmaXml.setDescripcionTipo(datosArmaDto.getDescripcionTipo());
                                datosArmaXml.setTipofabricante(datosArmaDto.getTipoFabricacion());
                                datosArmaXml.setMarca(datosArmaDto.getMarca());
                                datosArmaXml.setCalibre(datosArmaDto.getCalibre());
                                datosArmaXml.setModeloArma(datosArmaDto.getModelo());
                                datosArmaXml.setEstadoArma(datosArmaDto.getEstadoArma());
                                List<ImagenXml> listaImagen = new ArrayList<>();
                                if (institucion.equals(InstitucionSnapEnum.CRIMINALISTICA.getNombre())) {
                                    if (datosArmaDto.getImagenImpronta() != null && !"".equals(datosArmaDto.getImagenImpronta())) {
                                        listaImagen.add(new ImagenXml(parseToString(xPathLocation + datosArmaDto.getImagenImpronta()), "ImagenImpronta", FilenameUtils.getExtension(datosArmaDto.getImagenImpronta())));
                                    }
                                    if (datosArmaDto.getImagenArma() != null && !"".equals(datosArmaDto.getImagenArma())) {
                                        listaImagen.add(new ImagenXml(parseToString(xPathLocation + datosArmaDto.getImagenArma()), "ImagenArma", FilenameUtils.getExtension(datosArmaDto.getImagenArma())));
                                    }
                                }
                                if (datosArmaDto.getFichaTecnicaArma() != null && !"".equals(datosArmaDto.getFichaTecnicaArma())) {
                                    listaImagen.add(new ImagenXml(parseToString(xPathLocation + datosArmaDto.getFichaTecnicaArma()), "FichaTecnicaArma", FilenameUtils.getExtension(datosArmaDto.getFichaTecnicaArma())));
                                }
                                datosArmaXml.setListaImagen(listaImagen);

                                listaDatosArmaXml.add(datosArmaXml);
                            }
                            resultadoXml.setListaDatosArma(listaDatosArmaXml);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    EjecucionXml ejecucionXml = new EjecucionXml(1, "", "", "12345678");
                    SoapEnvelopWrapper soap = new SoapEnvelopWrapper(cabeceraXml, ejecucionXml, resultadoXml);
                    return soap;
                }
            }
        } else {
            CabeceraXml cabeceraXml = new CabeceraXml("XC001", formatoFecha.format(new Date()), formatoHora.format(new Date()));
            EjecucionXml ejecucionXml = new EjecucionXml(0, verificarDatos(institucion, nroDocumento, serie), "", "");
            ResultadoXml resultadoXml = new ResultadoXml();

            SoapEnvelopWrapper soap = new SoapEnvelopWrapper(cabeceraXml, ejecucionXml, resultadoXml);
            return soap;
        }
        // TODO Auto-generated method stub
        return null;
    }

    /**
     * Permite hacer la conversion de un archivo a String en Base 64
     *
     * @param path
     * @return
     */
    public String parseToString(String path) {
        AlfrescoApi api = new AlfrescoApi("comaco");
        try {
            InputStream is = api.downloadDocumentByXPathLocation(path);
            if (is != null) {
                byte[] targetArray = IOUtils.toByteArray(is);
                if (targetArray != null) {
                    Base64 obj = new Base64();
                    String aux = StringUtils.newStringUtf8(obj.encodeBase64(targetArray, false));
                    //System.out.println("aux prueba string---------------- : " + aux);
                    return aux;
                } else {
                    return null;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * Permite validar los datos de ingreso del WS
     *
     * @param institucion
     * @param nroDocumento
     * @param serie
     * @return
     */
    public String verificarDatos(String institucion, String nroDocumento, String serie) {
        if (institucion == null || "".equals(institucion)) {
            return "Debe ingresar la institucion";
        }

        if (nroDocumento == null || "".equals(nroDocumento)) {
            return "Debe ingresar la nroDocumento";
        }
        if (!institucion.equals(InstitucionSnapEnum.MINISTERIO_MINAS.getNombre())) {
            if (serie == null || "".equals(serie)) {
                return "Debe ingresar la serie";
            }
        }

        return "EXITO";
    }

    /**
     * Obtiene la informacion necesaria de armas a ser expuesta por el WS de
     * acuerdo a la institucion que solita.
     *
     * @param identificacion
     * @param institucion
     * @param serie
     * @return
     */
    public DatosSnapDto obtenerPersonDetail(String identificacion, String institucion, String serie) {
        // TODO Auto-generated method stub
        DatosSnapDto personaSnapDto = null;
        try {
            CallerHelper callerHelper = new CallerHelper();
            Request request = callerHelper.getRequest();
            request.setCompany(1);
            request.put("queryalias", "DATOSPERSONSNAP");
            request.put("identificacion", identificacion);
            request.put("institucion", institucion);
            request.put("serie", serie);
            Response response = callerHelper.executeQuery(request);
            if (response.getResponseCode().compareTo(Response.RESPONSE_OK) == 0) {
                personaSnapDto = (DatosSnapDto) response.get("DATOSPERSONSNAP");
            }
            return personaSnapDto;
        } catch (Throwable e) {
            APPLogger.getLogger().error(e.getMessage(), e);

            return null;
        }
    }

}
