/********************************************************************************
 * Copyright (c) 2018 Mettenmeier GmbH 
 *
 * See the NOTICE file(s) distributed with this work for additional 
 * information regarding copyright ownership.
 *
 * This program and the accompanying materials are made available under the 
 * terms of the Eclipse Public License 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0
 *
 * SPDX-License-Identifier: EPL-2.0 
 ********************************************************************************/
package org.eclipse.openk.sp.controller.reports;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.text.MessageFormat;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Random;
import java.util.Set;
import java.util.logging.Level;

import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.core.MediaType;

import org.apache.http.HttpStatus;
import org.apache.log4j.Logger;
import org.eclipse.birt.core.framework.Platform;
import org.eclipse.birt.report.engine.api.EXCELRenderOption;
import org.eclipse.birt.report.engine.api.EngineConfig;
import org.eclipse.birt.report.engine.api.EngineConstants;
import org.eclipse.birt.report.engine.api.IReportEngine;
import org.eclipse.birt.report.engine.api.IReportEngineFactory;
import org.eclipse.birt.report.engine.api.IReportRunnable;
import org.eclipse.birt.report.engine.api.IRunAndRenderTask;
import org.eclipse.birt.report.engine.api.PDFRenderOption;
import org.eclipse.birt.report.engine.api.RenderOption;
import org.eclipse.core.internal.registry.RegistryProviderFactory;
import org.eclipse.openk.common.Globals;
import org.eclipse.openk.sp.controller.AbstractController;
import org.eclipse.openk.sp.db.dao.StandbyGroupRepository;
import org.eclipse.openk.sp.db.dao.StandbyListRepository;
import org.eclipse.openk.sp.db.dao.StandbyScheduleBodyRepository;
import org.eclipse.openk.sp.db.dao.StandbyStatusRepository;
import org.eclipse.openk.sp.db.dao.UserRepository;
import org.eclipse.openk.sp.db.model.Address;
import org.eclipse.openk.sp.db.model.ContactData;
import org.eclipse.openk.sp.db.model.StandbyGroup;
import org.eclipse.openk.sp.db.model.StandbyList;
import org.eclipse.openk.sp.db.model.StandbyScheduleBody;
import org.eclipse.openk.sp.db.model.StandbyStatus;
import org.eclipse.openk.sp.db.model.User;
import org.eclipse.openk.sp.dto.report.ReportDto;
import org.eclipse.openk.sp.dto.report.ReportInputDto;
import org.eclipse.openk.sp.exceptions.SpErrorEntry;
import org.eclipse.openk.sp.exceptions.SpException;
import org.eclipse.openk.sp.exceptions.SpExceptionEnum;
import org.eclipse.openk.sp.rest.reports.ReportRestService;
import org.eclipse.openk.sp.util.DateHelper;
import org.eclipse.openk.sp.util.FileHelper;
import org.eclipse.openk.sp.util.ReportGroupDtoConverter;
import org.eclipse.openk.sp.util.ReportGroupNameDtoConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.google.gson.JsonElement;
import com.google.gson.JsonParser;

@Service
@Transactional(rollbackFor = Exception.class)
public class ReportController extends AbstractController {

	protected static final Logger LOGGER = Logger.getLogger(ReportController.class);

	@Autowired
	StandbyScheduleBodyRepository standbyScheduleBodyRepository;

	@Autowired
	StandbyStatusRepository standbyStatusRepository;

	@Autowired
	StandbyGroupRepository standbyGroupRepository;

	@Autowired
	ReportGroupDtoConverter reportGroupDtoConverter;

	@Autowired
	ReportGroupNameDtoConverter reportGroupDtoConverter2;

	@Autowired
	StandbyListRepository standbyListRepository;

	@Autowired
	UserRepository userRepository;

	@Autowired
	FileHelper fileHelper;

	protected List<Long> lsTempRemovalIds = new ArrayList<>();
	private String reportDirectory;
	private String workDirectory;
	private static final String REPORT_NAME = "report for ";
	private static final String APP_PROPERTIES_NAME = "/application.properties";
	public static final String REPORT_MAX10_GROUPS = "Diensthabende_MA_je_BG_(max._10)";
	public static final String REPORT_MAX10_GROUPS_ONLY_NAMES = "Diensthabende_MA_je_BG_(max._60)_nur_beginnende_Duration_pro_Tag";
	public static final String REPORT_ALL_GROUPS = "Diensthabende_MA_je_BG_Details";
	public static final String REPORT_ONE_USER = "Persönlicher_Einsatzplan";

	private static final Set<String> allowedReports = new HashSet<>(Arrays.asList("rptdesign"));
	private JsonElement reportConfig;

	public String init() {
		Properties property = null;
		try {
			property = fileHelper.loadPropertiesFromResource(APP_PROPERTIES_NAME);
			reportDirectory = property.getProperty("reports.path");
			workDirectory = property.getProperty("reports.workdirectory");

			File workDirectoryFile = fileHelper.loadFolderFromFileSystemOrResource(workDirectory, false);

			if (!workDirectoryFile.exists()) {
				LOGGER.info("the work directory for the files was not found! Creating one..");
				workDirectoryFile.mkdirs();
			}

			File reportConfigFile = fileHelper.loadFileFromFileSystemOrResource(reportDirectory, "config.json", false);

			if (!reportConfigFile.exists()) {
				LOGGER.error("a report config does not exist");
			} else {
				String content = new String(Files.readAllBytes(reportConfigFile.toPath()), StandardCharsets.UTF_8);
				JsonParser parser = new JsonParser();
				reportConfig = parser.parse(content);
			}

			return reportDirectory;
		} catch (IOException e) {
			LOGGER.error(e, e);
		}
		return null;
	}

	/**
	 * Method to query all reports.
	 * 
	 * @return
	 * @throws SpException
	 */
	public List<ReportDto> getReports() throws SpException {
		ArrayList<ReportDto> listReports = new ArrayList<>();
		try {
			init();

			for (File file : fileHelper.loadFolderFromFileSystemOrResource(reportDirectory, true).listFiles()) {

				String fileExtension = FileHelper.getFileExtension(file);
				if (allowedReports.contains(fileExtension)) {

					String reportName = file.getName();
					reportName = reportName.substring(0, reportName.lastIndexOf('.'));
					ReportDto reportDto = new ReportDto();
					reportDto.setReportName(reportName);

					int defaultDayRange = 7;
					// setting default dayrange
					if (reportName.equals(ReportController.REPORT_ALL_GROUPS)) {
						defaultDayRange = 30;
					}

					reportDto.setDefaultDayRange(defaultDayRange);
					listReports.add(reportDto);

				}
			}

			// sorting by reportname
			Collections.sort(listReports, (o1, o2) -> o1.getReportName().compareTo(o2.getReportName()));

			return listReports;
		} catch (Exception e) {
			SpErrorEntry ee = SpExceptionEnum.DEFAULT_EXCEPTION.getEntry();
			ee.setE(e);
			throw new SpException(ee);
		}
	}

	public File generateReport(ReportDto reportDto) throws SpException {
		List<ReportInputDto> inputDtos = null;

		if (reportDto.getReportName().equals(REPORT_MAX10_GROUPS)) {
			// 10 Gruppen Plan
			LOGGER.info(REPORT_NAME + REPORT_MAX10_GROUPS);
			inputDtos = reportGroupDtoConverter.get10Rows(reportDto);

		} else if (reportDto.getReportName().equals(REPORT_MAX10_GROUPS_ONLY_NAMES)) {
			// 60 Gruppen Plan
			LOGGER.info(REPORT_NAME + REPORT_MAX10_GROUPS_ONLY_NAMES);
			inputDtos = reportGroupDtoConverter2.get60Rows(reportDto);

		} else {
			// persönlicher Einsatzplan und Detailplan
			SpErrorEntry ee = SpExceptionEnum.NO_DATA_FOR_REPORT_FOUND.getEntry();
			List<StandbyScheduleBody> result = performReportQuery(reportDto);

			LOGGER.debug(result.size() + " records found for reporting");

			if (result.isEmpty()) {
				LOGGER.warn(ee.getMessage());
				throw new SpException(ee);
			}

			if (reportDto.getStandByList() != null) {
				LOGGER.info(REPORT_NAME + REPORT_ALL_GROUPS);
				inputDtos = compress2ResultOnGroups(reportDto, result);
			} else {

				// persönlicher Einsatzplan
				LOGGER.info(REPORT_NAME + REPORT_ONE_USER);
				inputDtos = compress1ResultOnGroups(reportDto, result);
			}

		}

		LOGGER.info("packing dataset for report with " + inputDtos.size() + " rows!");

		init();
		return generateBirtReport(reportDto.getReportName(), reportDto.getPrintFormat(), inputDtos, reportDto);
	}

	/**
	 * compress only bodies that are not interrupted
	 * 
	 * @param reportDto
	 * @param result
	 * @return
	 */
	private List<ReportInputDto> compressResultLevel1(List<ReportInputDto> reportInputDataSet, ReportDto reportDto,
			List<StandbyScheduleBody> result) {

		StandbyScheduleBody lastBody = null;

		for (StandbyScheduleBody standbyBody : result) {

			if (lastBody != null
					&& (lastBody.getUser().getId().longValue() == standbyBody.getUser().getId().longValue())
					&& (lastBody.getValidTo().compareTo(standbyBody.getValidFrom()) == 0)) {

				lastBody.setValidTo(standbyBody.getValidTo());

				calcReportEndDate(lastBody);

			} else {

				lastBody = standbyBody.copy();

				calcReportStartDate(lastBody);
				calcReportEndDate(lastBody);

				ReportInputDto reportInputDto = new ReportInputDto();
				reportInputDto.setReportDto(reportDto);
				reportInputDto.setStandbyScheduleBody(lastBody);

				reportInputDataSet.add(reportInputDto);
			}
		}

		return reportInputDataSet;
	}

	/**
	 * compress bodies as long as the user is not changed
	 * 
	 * @param reportDto
	 * @param result
	 * @param groupSort
	 * @return
	 */
	private List<ReportInputDto> compressResultLevel2(List<ReportInputDto> reportInputDataSet, ReportDto reportDto,
			List<StandbyScheduleBody> result, int groupSort) {

		StandbyScheduleBody lastBody = null;

		for (StandbyScheduleBody standbyBody : result) {

			if (lastBody != null
					&& lastBody.getUser().getId().longValue() == standbyBody.getUser().getId().longValue()) {
				lastBody.setValidTo(standbyBody.getValidTo());

				calcReportEndDate(lastBody);

			} else {

				lastBody = standbyBody.copy();

				calcReportStartDate(lastBody);
				calcReportEndDate(lastBody);

				ReportInputDto reportInputDto = new ReportInputDto();
				reportInputDto.setReportDto(reportDto);
				reportInputDto.setStandbyScheduleBody(lastBody);
				reportInputDto.setGroupSort(groupSort);

				reportInputDataSet.add(reportInputDto);
			}
		}

		return reportInputDataSet;
	}

	private List<ReportInputDto> compress2ResultOnGroups(ReportDto reportDto, List<StandbyScheduleBody> result) {

		List<ReportInputDto> reportInputDataSet = new ArrayList<>();

		StandbyList sbl = reportDto.getStandByList();
		List<StandbyGroup> groups = sbl.getLsStandbyGroups();
		Map<Long, List<StandbyScheduleBody>> groupMap = new HashMap<>();

		// init all Lists
		for (StandbyGroup standbyGroup : groups) {
			groupMap.put(standbyGroup.getId(), new ArrayList<StandbyScheduleBody>());
		}

		// sort by group
		for (StandbyScheduleBody body : result) {
			List<StandbyScheduleBody> groupList = groupMap.get(body.getStandbyGroup().getId());
			groupList.add(body);
			Collections.sort(groupList, (o1, o2) -> o1.getValidFrom().compareTo(o2.getValidFrom()));
		}

		int groupSort = 0;
		// compact
		for (StandbyGroup standbyGroup : groups) {
			LOGGER.debug("compactiong for group: " + standbyGroup.getTitle() + " on position " + groupSort);
			List<StandbyScheduleBody> groupList = groupMap.get(standbyGroup.getId());

			LOGGER.debug("from " + groupList.size() + " in " + reportInputDataSet.size());
			reportInputDataSet = compressResultLevel2(reportInputDataSet, reportDto, groupList, groupSort);

			groupSort++;
		}

		return reportInputDataSet;

	}

	public List<ReportInputDto> compress1ResultOnGroups(ReportDto reportDto, List<StandbyScheduleBody> result) {

		List<ReportInputDto> reportInputDataSet = new ArrayList<>();

		Map<Long, List<StandbyScheduleBody>> groupMap = new HashMap<>();

		// sort by group
		for (StandbyScheduleBody body : result) {

			Long groupId = body.getStandbyGroup().getId();
			if (groupMap.containsKey(groupId)) {

				List<StandbyScheduleBody> groupList = groupMap.get(groupId);
				groupList.add(body);
				Collections.sort(groupList, (o1, o2) -> o1.getValidFrom().compareTo(o2.getValidFrom()));
			} else {

				// init all List
				groupMap.put(groupId, new ArrayList<StandbyScheduleBody>());
				List<StandbyScheduleBody> groupList = groupMap.get(groupId);
				groupList.add(body);
			}
		}

		Set<Long> keySet = groupMap.keySet();

		for (Long groupId : keySet) {

			List<StandbyScheduleBody> groupList = groupMap.get(groupId);
			LOGGER.debug("compacting over groupId: " + groupId);

			LOGGER.debug("from " + groupList.size() + " in " + reportInputDataSet.size());
			compressResultLevel1(reportInputDataSet, reportDto, groupList);
		}
		return reportInputDataSet;
	}

	public void calcReportStartDate(StandbyScheduleBody body) {
		body.setStartDateStr(DateHelper.convertToLocalString(body.getValidFrom(), null));
	}

	public void calcReportEndDate(StandbyScheduleBody body) {
		body.setEndDateStr(DateHelper.convertToLocalString(body.getValidTo(), null));
	}

	public IReportEngine initialiseBirtEngine() {

		IReportEngine engine = null;
		try {
			final EngineConfig config = new EngineConfig();

			config.setLogConfig(workDirectory, Level.FINE);
			Platform.startup(config);

			IReportEngineFactory factory = (IReportEngineFactory) Platform
					.createFactoryObject(IReportEngineFactory.EXTENSION_REPORT_ENGINE_FACTORY);
			engine = factory.createReportEngine(config);
			engine.changeLogLevel(Level.WARNING);

			LOGGER.info("Successfully startet the BIRT engine");
		} catch (Exception e) {
			LOGGER.error(e, e);
		}
		return engine;

	}

	public File generateBirtReport(String reportName, String format, List<ReportInputDto> inputDtos,
			ReportDto reportDto) {

		String token = String.valueOf(new Random().nextLong());

		try (InputStream rptdFileStream = new FileInputStream(
				fileHelper.loadFileFromFileSystemOrResource(reportDirectory, reportName + ".rptdesign", true))) {
			LOGGER.info("Found design file " + reportName + ".rptdesign. inside " + reportDirectory);

			IReportEngine engine = initialiseBirtEngine();
			IReportRunnable iReportRunnable = engine.openReportDesign(rptdFileStream);
			IRunAndRenderTask task = engine.createRunAndRenderTask(iReportRunnable);
			task.getAppContext().put(EngineConstants.APPCONTEXT_CLASSLOADER_KEY,
					ReportController.class.getClassLoader());

			LOGGER.info("Filling reports with DATASET. Found [" + inputDtos.size() + "] items.");
			task.getAppContext().put("APP_CONTEXT_KEY_OK_DATASET", inputDtos);
			RenderOption options = null;

			setTaskParameters(task, reportDto);

			if (format.equals("xlsx")) {
				options = new EXCELRenderOption();
				options.setOutputFormat("xlsx");
			} else if (format.equals("xls")) {
				options = new EXCELRenderOption();
				options.setOutputFormat("xls");
			} else {
				options = new PDFRenderOption();
				options.setOutputFormat("pdf");
			}

			LOGGER.info("Format for the report is " + options.getOutputFormat());

			LOGGER.debug("outputFilePath: " + workDirectory + File.separator + reportName + "_" + token + "."
					+ options.getOutputFormat());

			options.setOutputFileName(
					workDirectory + File.separator + reportName + "_" + token + "." + options.getOutputFormat());
			task.setRenderOption(options);
			task.run();
			LOGGER.info("Report creation successfull. Shuting Engine down and closing task..");
			task.close();
			engine.destroy();
			Platform.shutdown();
			RegistryProviderFactory.releaseDefault();
		} catch (Exception e) {
			LOGGER.error("While creating the report something went terribly wrong", e);
		}
		return fileHelper.loadFileFromFileSystemOrResource(workDirectory, reportName + "_" + token + "." + format,
				true);
	}

	/**
	 * Method to get custom report text
	 * 
	 * @param planRequest
	 * @return
	 * @throws IOException
	 */
	public String customText(String templateFile, Object... obj) throws IOException {

		LOGGER.info("resource: " + templateFile);

		InputStream is = fileHelper.loadFileFromResource(templateFile);

		String newHtmlBody = null;
		if (is != null) {

			String htmlBody = FileHelper.getTextFromInputStream(is, StandardCharsets.UTF_8);

			newHtmlBody = MessageFormat.format(htmlBody, obj);

		}
		return newHtmlBody;

	}

	/**
	 * Setting the parameter values of a report
	 * 
	 * @param task
	 * @param inputDtos
	 */
	public boolean setTaskParameters(IRunAndRenderTask task, ReportDto reportDto) {

		String shortDatePattern = "dd.MM.yyyy";
		boolean isSet = true;
		try {
			LOGGER.info("read custom text for reports");

			String text1 = customText(Globals.REPORT_TEXT1);
			String text2 = customText(Globals.REPORT_TEXT2);
			String text3 = customText(Globals.REPORT_TEXT3);

			task.setParameterValue("customText1", text1);
			task.setParameterValue("customText2", text2);
			task.setParameterValue("customText3", text3);

		} catch (IOException e) {
			LOGGER.error("report properties could not be read!");
		}

		if (reportDto == null) {
			task.setParameterValue("liste", "--");
			task.setParameterValue("von", DateHelper.convertToString(null, shortDatePattern));
			task.setParameterValue("bis", DateHelper.convertToString(null, shortDatePattern));
			task.setParameterValue("reportLevel", "--");
			task.setParameterValue("reportName", "--");
			task.setParameterValue("user", "--");
		} else {

			if (reportDto.getStandByListId() != null && standbyListRepository.exists(reportDto.getStandByListId())) {
				StandbyList sbl = standbyListRepository.findOne(reportDto.getStandByListId());
				task.setParameterValue("liste", sbl.getTitle());
			} else {
				task.setParameterValue("liste", "--");
			}
			if (reportDto.getValidFromDate() != null) {

				String pattern = (reportDto.getReportName().equals(ReportController.REPORT_MAX10_GROUPS_ONLY_NAMES))
						? shortDatePattern
						: null;

				task.setParameterValue("von", DateHelper.convertToLocalString(reportDto.getValidFromDate(), pattern));
			}
			if (reportDto.getValidToDate() != null) {

				String pattern = (reportDto.getReportName().equals(ReportController.REPORT_MAX10_GROUPS_ONLY_NAMES))
						? shortDatePattern
						: null;

				task.setParameterValue("bis", DateHelper.convertToLocalString(reportDto.getValidToDate(), pattern));
			}
			if (reportDto.getStatusId() != null && standbyStatusRepository.exists(reportDto.getStatusId())) {
				StandbyStatus status = standbyStatusRepository.findOne(reportDto.getStatusId());
				task.setParameterValue("reportLevel", status.getTitle());
			} else {
				task.setParameterValue("reportLevel", "--");
			}

			if (reportDto.getReportName() != null) {
				task.setParameterValue("reportName", reportDto.getReportName());
			}

			if (reportDto.getUserId() != null && userRepository.exists(reportDto.getUserId())) {
				User user = userRepository.findOne(reportDto.getUserId());
				task.setParameterValue("user", user.getFirstname() + " " + user.getLastname());
			} else {
				task.setParameterValue("user", "--");
			}
		}

		Date currentDate = null;
		try {
			if (reportDto != null && reportDto.getCurrentDate() != null) {
				currentDate = DateHelper.getDateFromString(reportDto.getCurrentDate(), "yyyy-MM-dd'T'hh:mm:ss.SSS'Z'");
			}
		} catch (ParseException e) {
			LOGGER.error(e, e);
		}

		task.setParameterValue("created", DateHelper.convertToString(currentDate, "dd.MM.yyyy HH:mm:ss"));

		return isSet;
	}

	public List<StandbyScheduleBody> performReportQuery(ReportDto reportDto) throws SpException {

		Long[] groupIds = null;

		Date validFrom = (reportDto.getValidFromDate());
		Date validTo = (reportDto.getValidToDate());
		List<StandbyScheduleBody> result = null;
		Long reportLevel = reportDto.getStatusId();

		LOGGER.info("[" + validFrom + "," + validTo + "]");

		if (reportDto.getStandByGroup() != null) {
			LOGGER.info("report for one group");
			groupIds = new Long[1];
			groupIds[0] = reportDto.getStandByGroup().getId();

		} else if (reportDto.getStandByListId() != null && standbyListRepository.exists(reportDto.getStandByListId())) {
			LOGGER.info("report for many groups");

			StandbyList sbl = standbyListRepository.findOne(reportDto.getStandByListId());
			reportDto.setStandByList(sbl);
			List<StandbyGroup> groups = sbl.getLsStandbyGroups();

			int maxGroups = groups.size();

			if (groups.isEmpty()) {
				LOGGER.warn("performReportQuery: No groups in list! ");
				throw new SpException(HttpStatus.SC_METHOD_NOT_ALLOWED,
						"Es kann kein Report zu einer Liste ohne Guppen erstellt werden!", new Exception());
			}

			groupIds = new Long[maxGroups];

			for (int i = 0; i < maxGroups; i++) {
				groupIds[i] = groups.get(i).getId();
			}

		} else if (reportDto.getUserId() != null) {
			// Persönlicher Einsatzplan
			LOGGER.info("report for one person");
		} else {
			LOGGER.warn("performReportQuery: No group and no list is selected! ");
			throw new SpException(HttpStatus.SC_METHOD_NOT_ALLOWED,
					"performReportQuery: No group and no list is selected! ", new Exception());
		}

		if (reportDto.getUserId() != null) {
			LOGGER.info("query for one person");
			result = standbyScheduleBodyRepository.findByUserAndDateAndStatus(reportDto.getUserId(), validFrom, validTo,
					reportLevel);
		} else {
			LOGGER.info("query for groups");
			result = standbyScheduleBodyRepository.findData(groupIds, validFrom, validTo, reportLevel);

			Map<Long, StandbyGroup> foundGroups = new HashMap<>();

			// collect groups
			for (StandbyScheduleBody sbbody : result) {
				foundGroups.put(sbbody.getStandbyGroup().getId(), sbbody.getStandbyGroup());
			}
			List<StandbyScheduleBody> resultWithEmpty = new ArrayList<>();
			resultWithEmpty.addAll(result);

			// create empty body for empty group
			for (Long gId : groupIds) {
				if (!foundGroups.containsKey(gId)) {
					StandbyScheduleBody emptyBody = new StandbyScheduleBody();
					// setting dates
					emptyBody.setValidFrom(validFrom);
					emptyBody.setValidTo(validTo);

					// setting group
					emptyBody.setStandbyGroup(standbyGroupRepository.findOne(gId));

					// setting empty user
					User user = new User();
					user.setFirstname("");
					user.setLastname("");
					ContactData emptyContact = new ContactData();
					emptyContact.setPhone("");
					emptyContact.setCellphone("");
					emptyContact.setRadiocomm("");
					emptyContact.setPager("");
					user.setBusinessContactData(emptyContact);
					Address emptyAddress = new Address();
					emptyAddress.setCommunity("");
					user.setPrivateAddress(emptyAddress);
					user.setPrivateContactData(emptyContact);
					emptyBody.setUser(user);

					// add to result
					resultWithEmpty.add(emptyBody);
				}
			}

			result = resultWithEmpty;

		}

		return result;
	}

	public void flushReportFile(File reportFile, OutputStream out) {
		try (FileInputStream in = new FileInputStream(reportFile);) {

			byte[] buffer = new byte[4096];
			int length;
			while ((length = in.read(buffer)) > 0) {
				out.write(buffer, 0, length);
			}
			out.flush();
			if (reportFile.exists()) {
				in.close();
				Files.delete(reportFile.toPath());
			} else {
				throw new FileNotFoundException();
			}
		} catch (Exception e) {
			LOGGER.error(e, e);
		}
	}

	public void setResponseData(HttpServletResponse response, ReportDto reportDto) {
		if (reportDto.getPrintFormat().equals("xlsx")) {
			response.setContentType("application/octet-stream");
		} else if (reportDto.getPrintFormat().equals("pdf")) {
			response.setContentType(MediaType.APPLICATION_JSON);
		}

		response.setHeader("Content-Disposition",
				"attachment; filename=" + reportDto.getReportName() + "." + reportDto.getPrintFormat());
	}
}
