package gov.va.med.esr.common.batchprocess;

import gov.va.med.esr.common.model.lookup.StandardReport;
import gov.va.med.esr.common.model.report.CompletedReport;
import gov.va.med.esr.common.model.security.ESRUserPrincipal;
import gov.va.med.esr.common.model.security.ESRUserPrincipalImpl;
import gov.va.med.esr.common.persistent.report.ReportDAO;
import gov.va.med.esr.service.CommsEmailBulletinService;
import gov.va.med.esr.service.LookupService;
import gov.va.med.fw.batchprocess.AbstractDataFileListenerProcess;
import gov.va.med.fw.batchprocess.CampLejeuneImportProcessStatistics;
import gov.va.med.fw.batchprocess.DataFileProcessExecutionContext;
import gov.va.med.fw.batchprocess.DataProcessExecutionContext;
import gov.va.med.fw.batchprocess.ExceptionWriterProcessCompletedHandler;
import gov.va.med.fw.io.writer.FormattedFileWriter;
import gov.va.med.fw.persistent.DAOException;
import gov.va.med.fw.report.ReportExportedType;
import gov.va.med.fw.security.SecurityContextHelper;

import java.io.File;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.StringTokenizer;

import org.apache.commons.lang.StringUtils;

public class Import1095BResponsesPDFCompletedHandler extends
		ExceptionWriterProcessCompletedHandler {

	
	private static int FIRST_EXCETPION = 0;
	
	private FormattedFileWriter successFileWriter; //need to rename the input file after completion
	private FormattedFileWriter unSuccessFileWriter;
	private String toEmailList = null;
	
	private CommsEmailBulletinService bulletinService = null;
	
	private String renameInputFileExtension;

	private String renameInputFileRoot;
	
	private LookupService lookupService = null;
    private ReportDAO reportDAO = null;

	public String getRenameInputFileExtension() {
		return renameInputFileExtension;
	}

	public void setRenameInputFileExtension(String renameInputFileExtension) {
		this.renameInputFileExtension = renameInputFileExtension;
	}

	public String getRenameInputFileRoot() {
		return renameInputFileRoot;
	}

	public void setRenameInputFileRoot(String renameInputFileRoot) {
		this.renameInputFileRoot = renameInputFileRoot;
	}

	protected Object getExceptionFileNameSuffixData(
			DataProcessExecutionContext context) {
		Date executionStartDate = 
			context.getProcessStatistics().getProcessingStartDate();
		return executionStartDate;
	}

	// override dataProcessingComplete to allow append instead of writing to the
	// exception data file
	public void dataProcessingComplete(DataProcessExecutionContext context) {

		// append exception data instead of write
		writeDetailUnsuccessReport(context);
		
		//2.6.15.2.7 The 2 detail information reports (i.e., successful and unsuccessful activity) will be output as pipe-delimited files (i.e., csv) from each successful run of the batch process. 
		writeDetailSuccessReport(context);

		// delete input file (if any)
		if (!context.isInterrupted()) {
			if (context instanceof DataFileProcessExecutionContext) {
				File inputFile = ((DataFileProcessExecutionContext) context)
						.getCurrentFile();
				if (!renameFile(inputFile))
					throw new IllegalStateException(
							"Unable to rename input file: "
									+ inputFile.getName());
			}
		}
	}

	//change to access from ES UI Completed Report tab, instead of file
	public void writeDetailSuccessReport(DataProcessExecutionContext context) {
		
		CampLejeuneImportProcessStatistics stats = (CampLejeuneImportProcessStatistics)context.getProcessStatistics();

		String succData = stats.getDetailSuccess();
		
		//more than one line, cannot use NumberOfSuccessfulRecords > 0 because error reason is considered a success case
		if ( !StringUtils.isEmpty(succData) && succData.split("\n").length > 1) {
			CompletedReport report = new CompletedReport();
			report.setCompletedDate( Calendar.getInstance().getTime() );
			report.setUser( new ESRUserPrincipalImpl (SecurityContextHelper.getSecurityContext().getUserPrincipal().getName()));
			try {
				report.setStandardReport(lookupService.getStandardReportByCode(StandardReport.CODE_CLR_01.getCode()) );
				report.setFileType( lookupService.getReportExportedTypeByCode(ReportExportedType.CSV.getCode()) );
			} catch (Exception ex) {
				logger.error("Failed to lookup CLEAR Import Report Type:" + ex);
			}
			
			report.setReportFileContent(succData.getBytes());
			
		    try {
				reportDAO.saveCompletedReport( report );
			} catch( DAOException e ) {
					throw new IllegalStateException( "Failed to persist CLEAR Import Detail Successful Report", e );
			}
		}
	}
	
	//change to access from ES UI Completed Report tab, instead of file
	public void writeDetailUnsuccessReport(DataProcessExecutionContext context) {
		
		CampLejeuneImportProcessStatistics stats = (CampLejeuneImportProcessStatistics)context.getProcessStatistics();

		String unsuccData = stats.getDetailUnsuccess();
		
		//more than one line, cannot use NumberOfErrorRecords > 0 because error reason is considered a success case
		if ( !StringUtils.isEmpty(unsuccData) && unsuccData.split("\n").length > 1) { 
			CompletedReport report = new CompletedReport();
			report.setCompletedDate( Calendar.getInstance().getTime() );
			report.setUser( new ESRUserPrincipalImpl (SecurityContextHelper.getSecurityContext().getUserPrincipal().getName()));
			try {
				report.setStandardReport(lookupService.getStandardReportByCode(StandardReport.CODE_CLR_02.getCode()) );
				report.setFileType( lookupService.getReportExportedTypeByCode(ReportExportedType.CSV.getCode()) );
			} catch (Exception ex) {
				//log it
				logger.error("Failed to lookup CLEAR Import Report Type:" + ex);
			}
			
			report.setReportFileContent(unsuccData.getBytes());
			
		    try {
				reportDAO.saveCompletedReport( report );
			} catch( DAOException e ) {
					throw new IllegalStateException( "Failed to persist CLEAR Import Detail Unsuccessful Report", e );
			}

		}

	}
	
	
	private String getVeteranIdentifiers(String[] strs, boolean isParseError){
		
		if (isParseError) {
			String rawData = StringUtils.remove(strs[0], AbstractDataFileListenerProcess.ERROR_KEYWORD);
			String[] fields = rawData.split("\\|");
			
			return new StringBuffer(CampLejeuneImportProcessStatistics.DELIMITER). //empty vpid
			append(fields[3]).append(CampLejeuneImportProcessStatistics.DELIMITER).	//FirstName	
			append(fields[2]).append(CampLejeuneImportProcessStatistics.DELIMITER).	//LastName
			append(fields[5]).append(CampLejeuneImportProcessStatistics.DELIMITER).	//SSN
			append(fields[7]).append(CampLejeuneImportProcessStatistics.DELIMITER).	//DOB	
			append(fields[8]).append(CampLejeuneImportProcessStatistics.DELIMITER). //Gender
			append(strs[1]).toString(); //error reason
		
		} else {
			return new StringBuffer(StringUtils.remove(strs[0], CampLejeuneImportProcessSpawnedThreadTask.ERROR_KEYWORD)). //vpid|fn|ln|ssn|dob|gen
			append(CampLejeuneImportProcessStatistics.DELIMITER).
			append(strs[1]).toString(); //error reason
		}
	}

	protected boolean renameFile(File inputFile) {
		String inputFilePath = inputFile.getParent();
		StringBuffer inputFileNameRoot = new StringBuffer("");
		StringTokenizer st = new StringTokenizer(inputFile.getName(), ".");
		int tokenCount = st.countTokens();
		for (int i = 1; i < tokenCount; i++) {
			inputFileNameRoot.append(st.nextToken());
			if (i != (tokenCount - 1))
				inputFileNameRoot.append(".");
		}
		if (tokenCount == 1)
			inputFileNameRoot.append(inputFile.getName());

		String newFileName = null;
		if (renameInputFileRoot != null)
			newFileName = renameInputFileRoot + renameInputFileExtension;
		else
			newFileName = inputFileNameRoot.toString()
					+ renameInputFileExtension;
		File newFile = new File(inputFilePath + File.separator + newFileName);
		int i = 1;
		while (newFile.exists()) {
			if (logger.isWarnEnabled())
				logger.warn("Can not rename file to "
								+ newFile.getName()
								+ " since it exists already.  Trying one up number extension");

			newFile = new File(inputFilePath + File.separator + newFileName
					+ (i++));
		}
		boolean result = inputFile.renameTo(newFile);
		inputFile.setLastModified(new Date().getTime());
		return result;
	}

	public FormattedFileWriter getSuccessFileWriter() {
		return successFileWriter;
	}

	public void setSuccessFileWriter(FormattedFileWriter successFileWriter) {
		this.successFileWriter = successFileWriter;
	}

	public FormattedFileWriter getUnSuccessFileWriter() {
		return unSuccessFileWriter;
	}

	public void setUnSuccessFileWriter(FormattedFileWriter unSuccessFileWriter) {
		this.unSuccessFileWriter = unSuccessFileWriter;
	}

	public String getToEmailList() {
		return toEmailList;
	}

	public void setToEmailList(String toEmailList) {
		this.toEmailList = toEmailList;
	}

	public CommsEmailBulletinService getBulletinService() {
		return bulletinService;
	}

	public void setBulletinService(CommsEmailBulletinService bulletinService) {
		this.bulletinService = bulletinService;
	}

	public LookupService getLookupService() {
		return lookupService;
	}

	public void setLookupService(LookupService lookupService) {
		this.lookupService = lookupService;
	}

	public ReportDAO getReportDAO() {
		return reportDAO;
	}

	public void setReportDAO(ReportDAO reportDAO) {
		this.reportDAO = reportDAO;
	}


}
