/**
 *
 */
package com.fp.frontend.controller.alfresco;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.primefaces.context.RequestContext;
import org.primefaces.event.FileUploadEvent;
import org.primefaces.model.DefaultStreamedContent;
import org.primefaces.model.StreamedContent;
import org.primefaces.model.UploadedFile;

import com.fp.alfresco.client.AlfrescoApi;
import com.fp.alfresco.client.DocumentoAlfresco;
import com.fp.alfresco.exception.ExceptionWebscript;
import com.fp.alfresco.util.ApiProperties;
import com.fp.frontend.controller.pentaho.PentahoController;
import com.fp.frontend.controller.pgeneral.gene.ParametersController;
import com.fp.frontend.controller.security.LoginController;
import com.fp.frontend.helper.MessageHelper;
import com.fp.frontend.utility.EnumParametros;
import com.fp.frontend.utility.Utilidades;
import com.fp.persistence.pgeneral.gene.TgeneParameters;

/**
 * @author amerchan
 * @author dcruz
 *
 */
@ManagedBean
@ViewScoped
public class AlfrescoController implements Serializable {

    private static final long serialVersionUID = 1L;

    @ManagedProperty(value = "#{loginController}")
    private LoginController logincontroler;

    @ManagedProperty(value = "#{pentahoController}")
    private PentahoController pentahoController;

    private AlfrescoApi api;

    private List<DocumentoAlfresco> lDocuments;

    private List<DocumentoAlfresco> lUploadedDocuments;

    public AlfrescoController() {
        lUploadedDocuments = new ArrayList<DocumentoAlfresco>();
        api = new AlfrescoApi("comaco");
    }

    public boolean uploadFile(InputStream document, String fileName, String xPathLocation) {
        return uploadFile(null, document, fileName, xPathLocation);
    }

    public boolean uploadFile(String site, InputStream document, String fileName, String xPathLocation) {
        Boolean resp = Boolean.FALSE;
        try {
            fileName = Utilidades.caractersEspeciales(fileName);
        } catch (Exception e1) {
            e1.printStackTrace();
            MessageHelper.setMessageError(e1.getMessage());
            return Boolean.FALSE;
        }
        try {

            if (site != null) {
                api = new AlfrescoApi(site);
            }
            String name = FilenameUtils.getBaseName(fileName);
            String extension = FilenameUtils.getExtension(fileName);
            File archivoTemporal = File.createTempFile(name, extension);
            OutputStream outputStream = new FileOutputStream(archivoTemporal);
            IOUtils.copy(document, outputStream);
            IOUtils.closeQuietly(document);
            IOUtils.closeQuietly(outputStream);

            DocumentoAlfresco documentoAlfresco = api.findOneByXPathLocation(ApiProperties.getProperty("api.doclocation.base", api.getSite()) + "/" + xPathLocation + "/cm:" + fileName);
            if (documentoAlfresco != null && documentoAlfresco.getId() != null) {
//                DocumentoAlfresco docUpdate = documentoAlfresco.get(0);
                documentoAlfresco.setFile(archivoTemporal);
                documentoAlfresco.setNombre(fileName);
                api.uploadUpdateDocument(documentoAlfresco);
            } else {
                DocumentoAlfresco doc = new DocumentoAlfresco(fileName, logincontroler.getRequest().getUser());
                doc.setFile(archivoTemporal);
                doc.setNombre(fileName);
                api.uploadNewDocument(xPathLocation, doc);
            }
            resp = Boolean.TRUE;

        } catch (ExceptionWebscript e) {
            resp = Boolean.FALSE;
            MessageHelper.setMessageError(e.getMessage());
        } catch (Throwable e) {
            resp = Boolean.FALSE;
            e.printStackTrace();
            MessageHelper.setMessageError("msg_error_subir_arch");
        }
        return resp;
    }

    public boolean uploadFileWebService(InputStream document, String fileName, String xPathLocation, String user) {
        Boolean resp = Boolean.FALSE;

        try {

            String name = FilenameUtils.getBaseName(fileName);
            String extension = FilenameUtils.getExtension(fileName);
            File archivoTemporal = File.createTempFile(name, extension);
            OutputStream outputStream = new FileOutputStream(archivoTemporal);
            IOUtils.copy(document, outputStream);
            IOUtils.closeQuietly(document);
            IOUtils.closeQuietly(outputStream);
            DocumentoAlfresco documentoAlfresco = api.findOneByXPathLocation(ApiProperties.getProperty("api.doclocation.base", api.getSite()) + "/" + xPathLocation + "/cm:" + fileName);
            if (documentoAlfresco != null && documentoAlfresco.getId() != null) {
                documentoAlfresco.setFile(archivoTemporal);
                documentoAlfresco.setNombre(fileName);
                api.uploadUpdateDocument(documentoAlfresco);
            } else {
                DocumentoAlfresco doc = new DocumentoAlfresco(fileName, user);
                doc.setFile(archivoTemporal);
                doc.setNombre(fileName);
                api.uploadNewDocument(xPathLocation, doc);
            }
            resp = Boolean.TRUE;

        } catch (ExceptionWebscript e) {
            resp = Boolean.FALSE;
            MessageHelper.setMessageError(e.getMessage());
        } catch (Throwable e) {
            resp = Boolean.FALSE;
            e.printStackTrace();
            MessageHelper.setMessageError("msg_error_subir_arch");
        }
        return resp;
    }

    public void listenerUpload(FileUploadEvent event) {
        UploadedFile item = event.getFile();
        try {
            Utilidades.caractersEspeciales(item.getFileName());
        } catch (Exception e1) {
            e1.printStackTrace();
            MessageHelper.setMessageError(e1.getMessage());
            return;
        }
//        String[] nameArr = item.getFileName().split("[.]");
//        String name = nameArr[0];
//        String extension = nameArr[1];
        String name = FilenameUtils.getBaseName(item.getFileName());
        String extension = FilenameUtils.getExtension(item.getFileName());

        String xPathLocation = (String) event.getComponent().getAttributes().get("xPathLocation");
        if ((xPathLocation == null) || xPathLocation.isEmpty()) {
            MessageHelper.setMessageError("msg_location_req");
            return;
        }
        try {
            File archivoTemporal = File.createTempFile(name, extension);
            OutputStream outputStream = new FileOutputStream(archivoTemporal);
            InputStream inputStream = item.getInputstream();
            IOUtils.copy(inputStream, outputStream);
            IOUtils.closeQuietly(inputStream);
            IOUtils.closeQuietly(outputStream);

            DocumentoAlfresco doc = new DocumentoAlfresco(item.getFileName(), logincontroler.getRequest().getUser());
            doc.setFile(archivoTemporal);
            doc.setNombre(item.getFileName());
            doc = api.uploadNewDocument(xPathLocation, doc);
            doc.setFile(archivoTemporal);
            lUploadedDocuments.add(doc);
            RequestContext.getCurrentInstance().execute("onUploadAlfrescoListener()");
        } catch (ExceptionWebscript e) {
            MessageHelper.setMessageError(e.getMessage());
            return;
        } catch (Exception e) {
            e.printStackTrace();
            MessageHelper.setMessageError("msg_error_subir_arch");
        }
    }

    public byte[] downloadReturnDocument(String location) {
        FacesContext context = FacesContext.getCurrentInstance();
        ExternalContext external = context.getExternalContext();
//        HttpServletResponse response = (HttpServletResponse) external.getResponse();
        try {
            TgeneParameters parameters = ParametersController.find("PATH.ALFRESCO.ARCHIVOS", "1");
            String xPathLocation = parameters.getTextvalue() + location;
//        	xPathLocation+=(String) event.getComponent().getAttributes().get("xPathLocation");
            DocumentoAlfresco doc = null;
            if ((xPathLocation != null) && !xPathLocation.isEmpty()) {
                doc = api.findOneByXPathLocation(xPathLocation);
            }
            if (doc == null) {
                MessageHelper.setMessageError("msg_doc_no_existe");
                return null;
            }
//            response.setHeader("Pragma", "no-cache");
//            response.setDateHeader("Expires", 0);
//            response.setContentType("application/octet-stream");
//            response.setHeader("Content-Disposition", "attachment;filename=\"" + doc.getNombre() + "\"");

            InputStream inputStream = api.downloadDocumentByXPathLocation(xPathLocation);
            byte[] bytes = IOUtils.toByteArray(inputStream);
            return bytes;
//            OutputStream outputStream = response.getOutputStream();
//            IOUtils.copy(inputStream, outputStream);
//            IOUtils.closeQuietly(inputStream);
//            IOUtils.closeQuietly(outputStream);
        } catch (Exception e) {
            e.printStackTrace();
            MessageHelper.setMessageError("msg_error_bajar_arch");
            return null;
        }
//        context.responseComplete();
    }

    public void downloadDocument(ActionEvent event) {
        FacesContext context = FacesContext.getCurrentInstance();
        ExternalContext external = context.getExternalContext();
        HttpServletResponse response = (HttpServletResponse) external.getResponse();
        try {
            TgeneParameters parameters = ParametersController.find("PATH.ALFRESCO.ARCHIVOS", "1");
            String xPathLocation = parameters.getTextvalue();
            xPathLocation += (String) event.getComponent().getAttributes().get("xPathLocation");
            DocumentoAlfresco doc = null;
            if ((xPathLocation != null) && !xPathLocation.isEmpty()) {
                doc = api.findOneByXPathLocation(xPathLocation);
            }
            if (doc == null) {
                MessageHelper.setMessageError("msg_doc_no_existe");
                return;
            }
            response.setHeader("Pragma", "no-cache");
            response.setDateHeader("Expires", 0);
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment;filename=\"" + doc.getNombre() + "\"");

            InputStream inputStream = api.downloadDocumentByXPathLocation(xPathLocation);
            OutputStream outputStream = response.getOutputStream();
            IOUtils.copy(inputStream, outputStream);
            IOUtils.closeQuietly(inputStream);
            IOUtils.closeQuietly(outputStream);
        } catch (Exception e) {
            e.printStackTrace();
            MessageHelper.setMessageError("msg_error_bajar_arch");
            return;
        }
        context.responseComplete();
    }

    public static StreamedContent downloadDocument(String ruta) {
        FacesContext context = FacesContext.getCurrentInstance();
        ExternalContext external = context.getExternalContext();
        HttpServletResponse response = (HttpServletResponse) external.getResponse();
        try {
            TgeneParameters parameters = ParametersController.find("PATH.ALFRESCO.ARCHIVOS", "1");
            String xPathLocation = parameters.getTextvalue();
            xPathLocation += ruta;
            DocumentoAlfresco doc = null;
            AlfrescoApi api = new AlfrescoApi("comaco");
            if ((xPathLocation != null) && !xPathLocation.isEmpty()) {
                doc = api.findOneByXPathLocation(xPathLocation);
            }
            if (doc == null) {
                MessageHelper.setMessageError("msg_doc_no_existe");
                return null;
            }
            response.setHeader("Pragma", "no-cache");
            response.setDateHeader("Expires", 0);
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment;filename=\"" + doc.getNombre() + "\"");

            InputStream inputStream = api.downloadDocumentByXPathLocation(xPathLocation);
            return new DefaultStreamedContent(inputStream, "application/pdf", "TerminosCondiciones.pdf");
        } catch (Exception e) {
            e.printStackTrace();
            MessageHelper.setMessageError("msg_error_bajar_arch");
            return null;
        }
    }

    public void prepareDocumentList(ActionEvent event) {
        String xPathLocationFolder = (String) event.getComponent().getAttributes().get("xPathLocation");
        try {
            DocumentoAlfresco doc = api.findOneByXPathLocation(xPathLocationFolder);
            if (doc == null) {
                MessageHelper.setMessageError("msg_carp_no_existe", xPathLocationFolder);
                return;
            }
            lDocuments = api.findListByXPathLocation(xPathLocationFolder);
        } catch (Exception e) {
            e.printStackTrace();
            MessageHelper.setMessageError("msg_error_consulta_docs");
        }
    }

    public static InputStream getDocument(String name, String path) {

        AlfrescoController alfresco = new AlfrescoController();
        String xPath = path + name;

        InputStream input = null;
        try {

            input = alfresco.api.downloadDocumentByXPathLocation(xPath) != null ? alfresco.api.downloadDocumentByXPathLocation(xPath) : null;
        } catch (ExceptionWebscript e) {
            MessageHelper.setMessageError(e);
            input = null;
        } catch (Exception ex) {

        }
        return input;

    }

    /**
     * Descarga un documento Alfresco
     *
     * @param name
     * @param path
     * @return
     */
    public static InputStream getDocumentByCode(String codDocument, String nomTipo, String company) {

        AlfrescoController alfresco = new AlfrescoController();

        String xPath = ParametersController.find(EnumParametros.PATH_ALFRESCO.getCodigo(), company).getTextvalue() + codDocument + "/cm:" + nomTipo
                + "_" + codDocument + ".pdf";

        InputStream input = null;
        try {

            input = alfresco.api.downloadDocumentByXPathLocation(xPath) != null ? alfresco.api.downloadDocumentByXPathLocation(xPath) : null;
        } catch (ExceptionWebscript e) {
            MessageHelper.setMessageError(e);
            input = null;
        } catch (Exception ex) {
            // TODO Auto-generated catch block
        }
        return input;

    }

    /**
     * Carga un documento
     *
     * @param codDocument
     * @param nomTipo (solicitud - informe)
     * @throws Exception
     */
    /*public void uploadDocument(String codDocument, String nomTipo, String tipo) throws Exception {

        String reporte = nomTipo;
        Map<String, String> parameters = new HashMap<String, String>();
        parameters.put("cod_solicitud", codDocument);
        parameters.put("cod_tipo", tipo);

        this.uploadFile(pentahoController.generateTemporalReport(reporte, parameters, "pdf"), nomTipo + "_" + codDocument + ".pdf", "pdf",
                codDocument);
    }*/
    /**
     * Carga un documento
     *
     * @param codDocument
     * @param nomTipo (solicitud - informe)
     * @throws Exception
     */
    /*public static boolean uploadSignedDocument(InputStream document, String codDocument, String nomTipo) {

        AlfrescoController alfresco = new AlfrescoController();

        try {
            alfresco.uploadFile(document, nomTipo + "_" + codDocument + ".pdf", "pdf", codDocument);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }*/
    public boolean uploadDocumentRepository(InputStream document, String fileName, String xPathLocation) {
        return uploadDocumentRepository(null, document, fileName, xPathLocation);
    }

    /**
     * M&eacute;todo general de carga de documentos en alfresco
     *
     * @param document documento a cargar
     * @param site sitio a cargar el documento
     * @param fileName nombre con el que se cargara el archivo
     * @param xPathFile ruta dentro del sitio que se almacenara el documento
     * @return
     */
    public boolean uploadDocumentRepository(String site, InputStream document, String fileName, String xPathLocation) {
        Boolean resp = Boolean.FALSE;
        try {
            if (site != null) {
                api = new AlfrescoApi(site);
            }
            String name = FilenameUtils.getName(fileName);
            String extension = FilenameUtils.getExtension(fileName);
            File archivoTemporal = File.createTempFile(name, extension);
            OutputStream outputStream = new FileOutputStream(archivoTemporal);
            IOUtils.copy(document, outputStream);
            IOUtils.closeQuietly(document);
            IOUtils.closeQuietly(outputStream);

            DocumentoAlfresco doc = new DocumentoAlfresco(fileName, logincontroler.getRequest().getUser());
            doc.setFile(archivoTemporal);
            doc.setNombre(fileName);
            doc = api.uploadNewDocument(xPathLocation, doc);
            resp = true;
        } catch (Throwable e) {
            resp = false;
        }
        return resp;
    }

    /**
     * Carga un documento
     *
     * @param codDocument
     * @param nomTipo (solicitud - informe)
     * @throws Exception
     */
    /*public void uploadDocument(InputStream document, String codDocument, String nomTipo) throws Exception {

        this.uploadFile(document, nomTipo + "_" + codDocument + ".pdf", "pdf", codDocument);
    }*/
    /**
     * @return Retorna el atributo logincontroler
     */
    public LoginController getLogincontroler() {
        return logincontroler;
    }

    /**
     * @param logincontroler Parametro a fijar en el atributo logincontroler
     */
    public void setLogincontroler(LoginController logincontroler) {
        this.logincontroler = logincontroler;
    }

    /**
     * @return Retorna el atributo lDocuments
     */
    public List<DocumentoAlfresco> getlDocuments() {
        return lDocuments;
    }

    /**
     * @param lDocuments Parametro a fijar en el atributo lDocuments
     */
    public void setlDocuments(List<DocumentoAlfresco> lDocuments) {
        this.lDocuments = lDocuments;
    }

    /**
     * @return Retorna el atributo lUploadedDocuments
     */
    public List<DocumentoAlfresco> getlUploadedDocuments() {
        return lUploadedDocuments;
    }

    /**
     * @param lUploadedDocuments Parametro a fijar en el atributo
     * lUploadedDocuments
     */
    public void setlUploadedDocuments(List<DocumentoAlfresco> lUploadedDocuments) {
        this.lUploadedDocuments = lUploadedDocuments;
    }

    public void clearlUploadedDocuments() {
        if (lUploadedDocuments != null) {
            lUploadedDocuments.clear();
        } else {
            lUploadedDocuments = new ArrayList<DocumentoAlfresco>();
        }
    }

    /**
     * @return Retorna el atributo api
     */
    public AlfrescoApi getApi() {
        return api;
    }

    /**
     * @param Fija el par�metro del atributo api
     */
    public void setApi(AlfrescoApi api) {
        this.api = api;
    }

    /**
     * Entrega una instancia de PentahoController
     *
     * @return pentahoController
     */
    public PentahoController getPentahoController() {
        return pentahoController;
    }

    /**
     * Fija una instancia de PentahoController
     *
     * @param pentahoController
     */
    public void setPentahoController(PentahoController pentahoController) {
        this.pentahoController = pentahoController;
    }

}
