/*******************************************************************************
 * This file is part of Educatio.
 *
 *     Educatio is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 *
 *     Educatio is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU General Public License for more details.
 *
 *     You should have received a copy of the GNU General Public License
 *     along with Educatio.  If not, see <http://www.gnu.org/licenses/>.
 *     
 *     Authors:
 *           Filipe Marinho de Brito - filipe.marinho.brito@gmail.com
 *           Rodrigo de Souza Ataides - rodrigoataides@gmail.com
 *******************************************************************************/
package br.com.core.controle; 

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.nio.charset.Charset;
import java.security.Principal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Properties;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.sf.jasperreports.engine.JRAbstractExporter;
import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import net.sf.jasperreports.engine.design.JasperDesign;
import net.sf.jasperreports.engine.export.JRHtmlExporterParameter;
import net.sf.jasperreports.engine.xml.JRXmlLoader;

import org.apache.commons.io.IOUtils;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.jasperreports.AbstractJasperReportsSingleFormatView;
import org.springframework.web.servlet.view.jasperreports.JasperReportsCsvView;
import org.springframework.web.servlet.view.jasperreports.JasperReportsHtmlView;
import org.springframework.web.servlet.view.jasperreports.JasperReportsPdfView;
import org.springframework.web.servlet.view.jasperreports.JasperReportsXlsView;

import br.com.core.acl.modelo.PermissaoAcl;
import br.com.core.acl.util.AclUtils;
//import br.com.core.business.acl.CadastroBrasileiroOcupacaoAclBusiness;
import br.com.core.business.log.CadastroBrasileiroOcupacaoLogBusiness;
import br.com.core.business.persistencia.CadastroBrasileiroOcupacaoPersistenciaBusiness;
import br.com.core.conversor.CadastroBrasileiroOcupacaoConversor;
import br.com.core.datatable.business.DataTableBusiness;
import br.com.core.modelo.publico.CadastroBrasileiroOcupacao;
import br.com.core.modelo.publico.RamoSegurancaPublica;
import br.com.core.security.modelo.Usuario;
import br.com.core.util.HttpRequestUtils;
import flexjson.JSONDeserializer;
import flexjson.JSONException;
import flexjson.JSONSerializer;

@RequestMapping("CadastroBrasileiroOcupacao")
@Controller
public class CadastroBrasileiroOcupacaoController {

	@Autowired
	CadastroBrasileiroOcupacaoPersistenciaBusiness cadastroBrasileiroOcupacaoPersistenciaBusiness;
	@Autowired
	CadastroBrasileiroOcupacaoLogBusiness cadastroBrasileiroOcupacaoLogBusiness;
//	@Autowired
//	CadastroBrasileiroOcupacaoAclBusiness cadastroBrasileiroOcupacaoAclBusiness;
	@Autowired
	DataTableBusiness dataTableBusiness;


	@Transactional(readOnly=true)
	@RequestMapping(value="/bServerSide",headers = "Accept=application/json")
	@ResponseBody
	public ResponseEntity<String> listServerProcessingJson(@RequestBody String json, HttpServletRequest httpServletRequest) {
		HttpHeaders headers = new HttpHeaders();
		headers.add("Content-Type", "application/text; charset=utf-8");
		String dataTableJson = dataTableBusiness.jsonDataTableFromParameters(json,CadastroBrasileiroOcupacao.class);
		headers.add("Content-Length", dataTableJson.getBytes(Charset.forName("UTF-8")).length+"");
		return new ResponseEntity<String>(dataTableJson, headers, HttpStatus.OK);
	}

	@Transactional(readOnly=true)
	@RequestMapping(value="/bServerSide/{formato}")
	public void listServerProcessingRelatorio(@PathVariable("formato") String formato, @RequestParam("json") String json, Model uiModel, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {

		//construindo relatorio
		String fileName = "Relatório de CadastroBrasileiroOcupacao";
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		ServletOutputStream out = httpServletResponse.getOutputStream();
		JRAbstractExporter exporter = dataTableBusiness.gerarRelatorio(json, "Lista de CadastroBrasileiroOcupacao", fileName, baos, formato, CadastroBrasileiroOcupacao.class);

		//construindo o cabecalho
		String contentDisposition = null;
		String contentType = null;
		if (formato.equals("csv")) {
			contentDisposition = "attachment; filename=\"" + fileName + ".csv\"";
			contentType="application/text; charset=utf-8";
		} else if (formato.equals("html")) {
			contentDisposition = "attachment; filename=\"" + fileName + ".html\"";
			contentType="text/html; charset=utf-8";
		} else if (formato.equals("xls")) {
			contentDisposition = "attachment; filename=\"" + fileName + ".xls\"";
			contentType="application/vnd.ms-excel; charset=utf-8";
		} else {
			contentDisposition = "attachment; filename=\"" + fileName + ".pdf\"";
			contentType="application/pdf; charset=utf-8";
		}
		
		//construindo a resposta
		httpServletResponse.setHeader("Content-Disposition",contentDisposition);
		httpServletResponse.setHeader("Content-Disposition",contentType);
		httpServletResponse.setContentType(contentType);
		exporter.exportReport();
		byte[] relatorio = baos.toByteArray();
		IOUtils.copy(new ByteArrayInputStream(relatorio), out);
		out.flush();
	}

	@Transactional(readOnly=true)
	@RequestMapping(value = "/combo/{propriedade}",headers = "Accept=application/json")
	@ResponseBody
	public ResponseEntity<String> comboBoxJson(HttpServletRequest httpServletRequest, @PathVariable("propriedade") String propriedade, @RequestParam("ramoSeguranca") Long ramoSeguranca) {
		HttpHeaders headers = new HttpHeaders();
		headers.add("Content-Type", "application/json; charset=utf-8");
		String combo = new JSONSerializer().include("id").include(propriedade).exclude("*").serialize(cadastroBrasileiroOcupacaoPersistenciaBusiness.findByRamoSegurancaPublica(new RamoSegurancaPublica(ramoSeguranca)));
		headers.add("Content-Length", combo.getBytes(Charset.forName("UTF-8")).length+"");
		return new ResponseEntity<String>(combo, headers, HttpStatus.OK);
	}

	@Transactional(readOnly=true)
	@RequestMapping(method = RequestMethod.GET, value = "/{id}",headers = "Accept=application/json")
	@ResponseBody
	public ResponseEntity<String> getOne(HttpServletRequest httpServletRequest, @PathVariable("id") Long id) {
		CadastroBrasileiroOcupacao cadastroBrasileiroOcupacao= cadastroBrasileiroOcupacaoPersistenciaBusiness.find(id);
		String json = CadastroBrasileiroOcupacaoConversor.converterModeloParaJson(cadastroBrasileiroOcupacao);
		HttpHeaders headers = new HttpHeaders();
		headers.add("Content-Type", "application/json; charset=utf-8");
		headers.add("Content-Length", json.getBytes(Charset.forName("UTF-8")).length+"");
		return new ResponseEntity<String>(json, headers, HttpStatus.OK);
	}

	@Transactional(rollbackFor=Throwable.class)
	@RequestMapping(method = RequestMethod.POST, headers = "Accept=application/json")
	public ResponseEntity<String> createFromJson(@RequestBody String json, HttpServletRequest httpServletRequest, Principal principla) {

		Usuario currentUser = AclUtils.obterUsuario();
		cadastroBrasileiroOcupacaoLogBusiness.gerarLog(json, httpServletRequest, currentUser);
		CadastroBrasileiroOcupacao cadastroBrasileiroOcupacao = CadastroBrasileiroOcupacaoConversor.converterJsonParaModelo(json);
		cadastroBrasileiroOcupacaoPersistenciaBusiness.save(cadastroBrasileiroOcupacao);
//		cadastroBrasileiroOcupacaoAclBusiness.salvarPermissoesBasicasCadastroBrasileiroOcupacao(cadastroBrasileiroOcupacao);
		HttpHeaders headers = new HttpHeaders();
		headers.add("Content-Type", "application/json; charset=utf-8");
		return new ResponseEntity<String>(headers, HttpStatus.CREATED);
	}

	@RequestMapping(method = RequestMethod.GET, value = "/listar",produces = "text/html")
	public String listarCadastroBrasileiroOcupacao() {
		return "cadastrobrasileiroocupacao/listarCadastrobrasileiroocupacao";
	}

	@Transactional(readOnly=true)
	@RequestMapping(method = RequestMethod.GET, value = "/{id}", params = "formulario", headers = "Accept=application/json", produces = "text/html")
	public String getUpdateFormJson(@PathVariable("id") Long id, Model uiModel, HttpServletRequest httpServletRequest, Principal principla) {

		CadastroBrasileiroOcupacao cadastroBrasileiroOcupacao = cadastroBrasileiroOcupacaoPersistenciaBusiness.find(id);
		String json = CadastroBrasileiroOcupacaoConversor.converterModeloParaJson(cadastroBrasileiroOcupacao);
		uiModel.addAttribute("json",json);
		return "cadastrobrasileiroocupacao/mostrarCadastrobrasileiroocupacao";
	}

	@Transactional(readOnly=true)
	@RequestMapping(method = RequestMethod.GET, value = "/{id}", params ="compartilhamento", headers ="Accept=application/json",  produces = "text/html")
	public String getShareFormJson(@PathVariable("id") Long id, Model uiModel, HttpServletRequest httpServletRequest, Principal principla) {
		CadastroBrasileiroOcupacao cadastroBrasileiroOcupacao = cadastroBrasileiroOcupacaoPersistenciaBusiness.find(id);
//		List<PermissaoAcl> permissoes = cadastroBrasileiroOcupacaoAclBusiness.obterPerfisComAcessoCadastroBrasileiroOcupacao(cadastroBrasileiroOcupacao);
		JSONObject jsonObject = new JSONObject();
		jsonObject.put("id", id);
		jsonObject.put("tipo", "CadastroBrasileiroOcupacao");
//		jsonObject.put("permissoes", permissoes);
		String json = jsonObject.toString();
		uiModel.addAttribute("json",json);
		return "share/compartilhar";
	}

	@RequestMapping(method = RequestMethod.GET, value = "/mostrar",produces = "text/html")
	public String mostrarCadastroBrasileiroOcupacao() {
		return "cadastrobrasileiroocupacao/mostrarCadastrobrasileiroocupacao";
	}

	@Transactional(rollbackFor=Throwable.class)
	@RequestMapping(method = RequestMethod.PUT, headers = "Accept=application/json")
	public ResponseEntity<String> updateFromJson(@RequestBody String json, HttpServletRequest httpServletRequest, Principal principla) {

		Usuario currentUser = AclUtils.obterUsuario();
		CadastroBrasileiroOcupacao cadastroBrasileiroOcupacaoAntigo = cadastroBrasileiroOcupacaoPersistenciaBusiness.find(new JSONObject(json).getLong("id"));
		cadastroBrasileiroOcupacaoLogBusiness.gerarLog(cadastroBrasileiroOcupacaoAntigo, json, httpServletRequest, currentUser);
		CadastroBrasileiroOcupacao cadastroBrasileiroOcupacao = CadastroBrasileiroOcupacaoConversor.converterJsonParaModelo(json);
		cadastroBrasileiroOcupacaoPersistenciaBusiness.update(cadastroBrasileiroOcupacao);
//		cadastroBrasileiroOcupacaoAclBusiness.atualizarPermissoesCadastroBrasileiroOcupacao(cadastroBrasileiroOcupacao,cadastroBrasileiroOcupacaoAntigo);
		HttpHeaders headers = new HttpHeaders();
		headers.add("Content-Type", "application/json; charset=utf-8");
		return new ResponseEntity<String>(headers, HttpStatus.OK);
	}

	@Transactional(rollbackFor=Throwable.class)
	@RequestMapping(method = RequestMethod.DELETE, value = "/{id}", headers = "Accept=application/json")
	public ResponseEntity<String> deleteFromJson(@PathVariable("id") Long id, HttpServletRequest httpServletRequest, Principal principla) {

		Usuario currentUser = AclUtils.obterUsuario();
		cadastroBrasileiroOcupacaoLogBusiness.gerarLog("{\"id\" : \""+id+"\"}", httpServletRequest, currentUser);
		CadastroBrasileiroOcupacao cadastroBrasileiroOcupacao = cadastroBrasileiroOcupacaoPersistenciaBusiness.find(id);
		cadastroBrasileiroOcupacaoPersistenciaBusiness.delete(cadastroBrasileiroOcupacao);
//		cadastroBrasileiroOcupacaoAclBusiness.removerTodasAsPermissoesCadastroBrasileiroOcupacao(cadastroBrasileiroOcupacao);
		HttpHeaders headers = new HttpHeaders();
		headers.add("Content-Type", "application/json; charset=utf-8");
		return new ResponseEntity<String>(headers, HttpStatus.OK);
	}

	@ExceptionHandler(Throwable.class)
	@ResponseBody
	public ResponseEntity<java.lang.String> handleException(Exception ex) {
	if(!(ex instanceof org.springframework.security.access.AccessDeniedException)){
		ex.printStackTrace();
 	}
		JSONException je = HttpRequestUtils.transcriptException(ex);
			HttpHeaders headers = new HttpHeaders();
			headers.add("Content-Type", "application/json; charset=utf-8");
			String json = new JSONSerializer().exclude("*.class").exclude("cause").exclude("message").exclude("stackTraceDepth").serialize(je);
			return new ResponseEntity<String>(json, headers, HttpStatus.INTERNAL_SERVER_ERROR);
	}

	@Transactional(readOnly=true)
	@RequestMapping("/relatorio/{id}")
	public ModelAndView geraRelatorioMultiformato(@PathVariable("id") Long id,    @RequestParam(value = "formato", required = false) String formato, Model uiModel, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
		List<CadastroBrasileiroOcupacao> dataSourceList = new ArrayList<CadastroBrasileiroOcupacao>();
		CadastroBrasileiroOcupacao cadastroBrasileiroOcupacao = cadastroBrasileiroOcupacaoPersistenciaBusiness.find(id);
		dataSourceList.add(cadastroBrasileiroOcupacao);
		JRBeanCollectionDataSource dataSource = new JRBeanCollectionDataSource(dataSourceList, false);
		
 		String fileName = "Relatório de Cadastro Brasileiro Ocupacao";
		String barra =System.getProperty("file.separator");
		String path = "WEB-INF" + barra + "reports" + barra + "cadastrobrasileiroocupacao" + barra + "relatorioCadastroBrasileiroOcupacao"+".jrxml";
		String fullPathJrxml = httpServletRequest.getSession().getServletContext().getRealPath("/") + path;

		//recompilando o relatorio pai para setar as margens
 		JasperDesign jasperDesign = JRXmlLoader.load(fullPathJrxml);
		jasperDesign.setTopMargin(20);
 		jasperDesign.setBottomMargin(20);
		jasperDesign.setLeftMargin(20);
		jasperDesign.setRightMargin(20);
		JasperCompileManager.writeReportToXmlFile(jasperDesign, fullPathJrxml);
		
		AbstractJasperReportsSingleFormatView jasperView = null;
		String availableHeaders = null;
		if (formato.equals("csv")) {
			jasperView = new JasperReportsCsvView();
			availableHeaders = "attachment; filename=\"" + fileName + ".csv\"";
		} else if (formato.equals("html")) {
			jasperView = new JasperReportsHtmlView();
			availableHeaders = "attachment; filename=\"" + fileName + ".html\"";
			HashMap<JRHtmlExporterParameter, Boolean> parameters = new HashMap<JRHtmlExporterParameter, Boolean>();
			parameters.put(JRHtmlExporterParameter.IS_USING_IMAGES_TO_ALIGN, false);
			jasperView.setExporterParameters(parameters);
		} else if (formato.equals("xls")) {
			jasperView = new JasperReportsXlsView();
			availableHeaders = "attachment; filename=\"" + fileName + ".xls\"";
		} else {
 			jasperView = new JasperReportsPdfView();
			availableHeaders = "attachment; filename=\"" + fileName + ".pdf\"";
		}
 		
 		Properties headers = new Properties();
		headers.put("Content-Disposition", availableHeaders);
		jasperView.setUrl(path);
		jasperView.setApplicationContext(WebApplicationContextUtils.getRequiredWebApplicationContext(httpServletRequest.getSession().getServletContext()));
		jasperView.setHeaders(headers);
 		jasperView.setReportDataKey("datasource");
		uiModel.asMap().put("datasource", dataSource);
		uiModel.asMap().put("pai", true);

		return new ModelAndView(jasperView, uiModel.asMap());
	}

	@Transactional(rollbackFor=Throwable.class)
	@RequestMapping(method = RequestMethod.POST, value = "/modificarPermissoes",headers = "Accept=application/json")
	public ResponseEntity<String> modificarPermissoes(@RequestBody String json, HttpServletRequest httpServletRequest){
		Usuario currentUser = AclUtils.obterUsuario();
		JSONObject jsonObject = new JSONObject(json);
		Long id = Long.parseLong(jsonObject.get("id").toString());
		List<PermissaoAcl> permissoes = new JSONDeserializer<List<PermissaoAcl>>().use(null, ArrayList.class).use("values", PermissaoAcl.class).deserialize(jsonObject.get("permissoes").toString());
		CadastroBrasileiroOcupacao cadastroBrasileiroOcupacao = cadastroBrasileiroOcupacaoPersistenciaBusiness.find(id);
		for (PermissaoAcl permissaoAcl : permissoes) {
			if(permissaoAcl.isRead()){
//				cadastroBrasileiroOcupacaoAclBusiness.adicionarPermissoesCadastroBrasileiroOcupacao("read", cadastroBrasileiroOcupacao, permissaoAcl.getPerfil());
			}else{
//				cadastroBrasileiroOcupacaoAclBusiness.removerPermissoesCadastroBrasileiroOcupacao("read", cadastroBrasileiroOcupacao, permissaoAcl.getPerfil());
			}
			if(permissaoAcl.isWrite()){
//				cadastroBrasileiroOcupacaoAclBusiness.adicionarPermissoesCadastroBrasileiroOcupacao("write", cadastroBrasileiroOcupacao, permissaoAcl.getPerfil());
			}else{
//				cadastroBrasileiroOcupacaoAclBusiness.removerPermissoesCadastroBrasileiroOcupacao("write", cadastroBrasileiroOcupacao, permissaoAcl.getPerfil());
			}
			if(permissaoAcl.isDel()){
//				cadastroBrasileiroOcupacaoAclBusiness.adicionarPermissoesCadastroBrasileiroOcupacao("delete", cadastroBrasileiroOcupacao, permissaoAcl.getPerfil());
			}else{
//				cadastroBrasileiroOcupacaoAclBusiness.removerPermissoesCadastroBrasileiroOcupacao("delete", cadastroBrasileiroOcupacao, permissaoAcl.getPerfil());
			}
			if(permissaoAcl.isAdminister()){
//				cadastroBrasileiroOcupacaoAclBusiness.adicionarPermissoesCadastroBrasileiroOcupacao("administration", cadastroBrasileiroOcupacao, permissaoAcl.getPerfil());
			}else{
//				cadastroBrasileiroOcupacaoAclBusiness.removerPermissoesCadastroBrasileiroOcupacao("administration", cadastroBrasileiroOcupacao, permissaoAcl.getPerfil());
			}
		}
		cadastroBrasileiroOcupacaoLogBusiness.gerarLog(json, httpServletRequest, currentUser);		
		HttpHeaders headers = new HttpHeaders();
		headers.add("Content-Type", "application/json; charset=utf-8");
		return new ResponseEntity<String>(headers, HttpStatus.OK);
	}

}
