package br.mp.mprj.portal.portlet.gestaomensagens.util;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import javax.portlet.PortletRequest;
import javax.portlet.PortletSession;

import com.liferay.portal.NoSuchImageException;
import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.kernel.repository.model.FileEntry;
import com.liferay.portal.kernel.repository.model.Folder;
import com.liferay.portal.kernel.upload.UploadPortletRequest;
import com.liferay.portal.kernel.util.FileUtil;
import com.liferay.portal.kernel.util.GetterUtil;
import com.liferay.portal.kernel.util.MimeTypesUtil;
import com.liferay.portal.kernel.util.StringPool;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.kernel.util.WebKeys;
import com.liferay.portal.service.ServiceContext;
import com.liferay.portal.service.ServiceContextFactory;
import com.liferay.portal.theme.ThemeDisplay;
import com.liferay.portal.util.PortalUtil;
import com.liferay.portlet.documentlibrary.NoSuchFolderException;
import com.liferay.portlet.documentlibrary.model.DLFolder;
import com.liferay.portlet.documentlibrary.service.DLAppLocalServiceUtil;
import com.liferay.portlet.documentlibrary.util.DLUtil;
import com.liferay.util.portlet.PortletProps;

public class DocumentFileUtil {
	
	/**
	 * Express&atilde;o regular para ser utilizado na exclus&atilde;o da extens&atilde;o do nome do arquivo.
	 */
	public static final String EXPR_EXTENSAO = "(\\.*[\\w]*)$";
	
	public static final String MIME_APPLICATION = "application/octet-stream";

	/**
	 * Nome do atributo que cont&eacute;m o ID da pasta principal de imagem.
	 */
	public static final String ATRIBUTO_PASTA_ANEXO_MENSAGEM_ID = "PORTLET_PASTA_ANEXO_MENSAGEM_ID";
	
	/**
	 * Descri&ccedil;&atilde;o da pasta principal do portlet na galeria de imagens.
	 */
	public static final String DESCRICAO_PASTA_ANEXOS_PRINCIPAL = GetterUtil.getString(PortletProps.get("descricao-pasta-principal-anexos"));
	
	public static final String PASTA_ANEXOS_PRINCIPAL = GetterUtil.getString(PortletProps.get("nome-pasta-principal-anexos"));
		
	public static final String URI_ARQUIVO = GetterUtil.getString(PortletProps.get("url.arquivo"));
	
	protected final ServiceContext serviceContext;
	protected final long userId;
	protected final long groupId;
	protected final long idPastaPrincipal;
	protected final PortletRequest portletRequest;
	
	public DocumentFileUtil(long groupId, long userId, PortletRequest portletRequest) throws SystemException, PortalException {
		this.portletRequest = portletRequest;
		this.userId = userId;
		this.groupId = groupId;
		this.serviceContext = getServiceContext();
		this.idPastaPrincipal = pesquisarPastaPrincipal();
	}
	
	public ServiceContext getServiceContext() throws SystemException, PortalException {
		ServiceContext sc = ServiceContextFactory.getInstance(DLFolder.class.getName(), portletRequest);
		sc.setAddGroupPermissions(true);
		sc.setAddGuestPermissions(true);
		return sc;
	}
	
	/**
	 * Criar um arquivo no Documentos e M&iacute;dias
	 * @param folderId - id da pasta
	 * @param nome - nome do arquivo
	 * @param arquivo - objeto representando o arquivo fisicamente no servidor
	 * @param contentType - tipo de conteudo do arquivo
	 * @return FileEntry
	 * @throws SystemException
	 * @throws PortalException
	 */	
	public FileEntry criarArquivo(long folderId, String nome, File arquivo, String contentType) throws SystemException, PortalException {
		return DLAppLocalServiceUtil.addFileEntry(userId, groupId, folderId, arquivo.getName(), contentType, nome, DESCRICAO_PASTA_ANEXOS_PRINCIPAL,
				StringPool.BLANK, arquivo, serviceContext);
	}
	
	/**
	 * Atualizar um arquivo no Documentos e M&iacute;dias
	 * @param userId - id do usu&aacute;rio
	 * @param nome - nome do arquivo
	 * @param arquivo - objeto representando o arquivo fisicamente no servidor
	 * @param contentType - tipo de conteudo do arquivo
	 * @return FileEntry
	 * @throws SystemException
	 * @throws PortalException
	 */
	public FileEntry atualizarArquivo(long userId, long fileEntryId, String nome, File arquivo, String contentType)
			throws SystemException, PortalException {
		return DLAppLocalServiceUtil.updateFileEntry(userId, fileEntryId, arquivo.getName(), contentType, nome, DESCRICAO_PASTA_ANEXOS_PRINCIPAL,
				StringPool.BLANK, true, arquivo, serviceContext);
	}
	
	/**
	 * Busca o arquivo por nome no diret&oacute;rio especificado.
	 * @param groupId
	 * @param folderId
	 * @param nome - nome do arquivo a ser pesquisado no Documentos e M&iacute;dias.
	 * @return FileEntry
	 * @throws SystemException
	 * @throws PortalException
	 */
	public FileEntry getArquivoPorNome(long groupId, long folderId, String nome) throws SystemException {
		try {
			return DLAppLocalServiceUtil.getFileEntry(groupId, folderId, nome);
		} catch (PortalException e) {
			return null;
		}
	}
	
	/**
	 * Busca o arquivo por id no diret&oacute;rio especificado.
	 * @param id - id do arquivo a ser pesquisado no Documentos e M&iacute;dias.
	 * @return FileEntry
	 * @throws SystemException
	 * @throws PortalException
	 */
	public static FileEntry getArquivoPorId(long id) throws SystemException {
		try {
			return DLAppLocalServiceUtil.getFileEntry(id);
		} catch (PortalException e) {
			return null;
		}
	}
	
	/**
	 * Retorna o ID (folderId) da pasta principal dos arquivos do portlet no Documentos e M&iacute;dias.<br>
	 * Este ID &eacute; definido no construtor desta classe utilit&aacute;ria.
	 * @return long - folderId
	 */
	public long getIdPastaPrincipal() {
		return idPastaPrincipal;
	}
	
	/**
	 * Verifica se a pasta de arquivos existe (pesquisando pelo nome na pasta principal informada), caso contr&aacute;rio, 
	 * ser&aacute; criada de acordo com as informa&ccedil;&otilde;es dos par&acirc;metros.
	 * @param groupId
	 * @param pastaPrincipalId - id da pasta principal (pai) onde ser&aacute; feita a pesquisa/cria&ccedil;&atilde;o
	 * @param nomePasta - nome da pasta a ser pesquisada/criada
	 * @param titulo - descri&ccedil;&atilde;o da pasta caso haja necessidade de ser criada
	 * @return Folder
	 * @throws PortalException
	 * @throws SystemException
	 */
	public Folder verificarPastaArquivos(long pastaPrincipalId, String nomePasta, String titulo) throws PortalException, SystemException {
		return verificarPastaArquivos(pastaPrincipalId, nomePasta, titulo, serviceContext);
	}
	
	/**
	 * Verifica se a pasta de arquivos existe (pesquisando pelo nome na pasta principal informada), caso contr&aacute;rio, 
	 * ser&aacute; criada de acordo com as informa&ccedil;&otilde;es dos par&acirc;metros.
	 * @param groupId
	 * @param pastaPrincipalId - id da pasta principal (pai) onde ser&aacute; feita a pesquisa/cria&ccedil;&atilde;o
	 * @param nomePasta - nome da pasta a ser pesquisada/criada
	 * @param titulo - descri&ccedil;&atilde;o da pasta caso haja necessidade de ser criada
	 * @param serviceContext
	 * @return Folder
	 * @throws PortalException
	 * @throws SystemException
	 */
	private Folder verificarPastaArquivos(long pastaPrincipalId, String nomePasta, String titulo, ServiceContext serviceContext)
			throws PortalException, SystemException {
		try {
			return DLAppLocalServiceUtil.getFolder(groupId, pastaPrincipalId, nomePasta);
		} catch (NoSuchFolderException ex) {
			//return FolderServiceUtil.addFolder(pastaPrincipalId, nomePasta, titulo, serviceContext);
			return DLAppLocalServiceUtil.addFolder(userId, groupId, pastaPrincipalId, nomePasta, titulo, serviceContext);
		}
	}
	
	/**
	 * Pesquisar o ID da pasta principal das imagens do portlet no Documentos e M&iacute;dias.
	 * @return Folder
	 */
	private long pesquisarPastaPrincipal() throws SystemException {
		try {
			PortletSession session = portletRequest.getPortletSession();
			Long idPasta = (Long)session.getAttribute(ATRIBUTO_PASTA_ANEXO_MENSAGEM_ID, PortletSession.PORTLET_SCOPE);
			if (idPasta == null) {
				Folder pasta = null;
				try {
					pasta = DLAppLocalServiceUtil.getFolder(groupId, 0L, PASTA_ANEXOS_PRINCIPAL);
				}
				catch (NoSuchFolderException ex) {
					pasta = DLAppLocalServiceUtil.addFolder(
							userId, groupId, 0L, PASTA_ANEXOS_PRINCIPAL, DESCRICAO_PASTA_ANEXOS_PRINCIPAL, serviceContext);
				}
				idPasta = pasta.getFolderId();
				session.setAttribute(ATRIBUTO_PASTA_ANEXO_MENSAGEM_ID, idPasta, PortletSession.PORTLET_SCOPE);
			}
			return idPasta;
		}
		catch (PortalException ex) {
			throw new SystemException("Pasta principal de arquivos não encontrada!", ex);
		}		
	}
	
	/**
	 * Cria a URL para exibi&ccedil;&atilde;o do arquivo na galeria do Liferay.
	 * @param arquivo - objeto arquivo a ser criada a URL.
	 * @param urlBaseArquivo - url base para acessar o arquivo
	 * @return String
	 */
	public String criarUrlArquivo(FileEntry arquivo, String urlBaseArquivo) throws SystemException, PortalException {
		ThemeDisplay themeDisplay = (ThemeDisplay) (PortalUtil.getUploadPortletRequest(portletRequest)).getAttribute(WebKeys.THEME_DISPLAY);
		return DLUtil.getPreviewURL(arquivo, arquivo.getFileVersion(), themeDisplay, StringPool.BLANK, false, false);
	}
	
	/**
	 * Cria a URL para exibi&ccedil;&atilde;o do arquivo na galeria do Liferay.
	 * Utilizando como URI base o valor definido na propriedade url-arquivo do portlet.properties.
	 * @param arquivo - objeto arquivo a ser criada a URL.
	 * @return String
	 */
	public String criarUrlArquivo(FileEntry arquivo) throws SystemException, PortalException {
		return criarUrlArquivo(arquivo, URI_ARQUIVO);
	}
	
	/**
	 * Retornar o tipo de conte&uacute;do do arquivo.
	 * @param uploadRequest
	 * @param file
	 * @param nomeCampoFile
	 * @return
	 */
	public static String getContentTypeFile(UploadPortletRequest uploadRequest, File file, String nomeCampoFile) {

		String contentType = GetterUtil.getString(uploadRequest.getContentType(nomeCampoFile));

		if (contentType.equals(MIME_APPLICATION)) {
			String ext = GetterUtil.getString(FileUtil.getExtension(file.getName())).toLowerCase();

			if (Validator.isNotNull(ext)) {
				contentType = MimeTypesUtil.getContentType(ext);
			}
		}

		return contentType;
	}
	
	/**
	 * Excluir o arquivo do Liferay.
	 * @param fileId
	 * @throws SystemException
	 * @throws PortalException
	 */
	public void removerArquivo(long fileId) throws SystemException, PortalException {
		try {
			DLAppLocalServiceUtil.deleteFileEntry(fileId);
		}
		catch (NoSuchImageException ex) {} //ignora a exception de arquivo não encontrado
	}

	public static String getTamanhoArquivo(double sizeOriginal) {
		int size = (int) sizeOriginal;
		String tamanho = size + "byte";
		if (size >= 1073741824) {
			tamanho = (size / 1073741824) + "GB";
		} else if (size >= 1048576) {
			tamanho = (size / 1048576) + "MB";
		} else if (size >= 1024) {
			tamanho = (size / 1024) + "KB";
		}
		return tamanho;
	}
	
}
