package cdac.medinfo.sdk.hl7282.tool.hl7messagevalidator;

import java.io.IOException;

import cdac.medinfo.sdk.hl7282.baselibs.messages.HL7MessageValidator;
import cdac.medinfo.sdk.hl7282.baselibs.messages.MessageFactory;
import cdac.medinfo.sdk.hl7282.exceptions.InvalidMessageException;
import cdac.medinfo.sdk.hl7282.hl7model.messages.applicationmanagement.AppMgtRecepient;
import cdac.medinfo.sdk.hl7282.hl7model.messages.applicationmanagement.AppMgtSource;
import cdac.medinfo.sdk.hl7282.hl7model.messages.clinicallaboratoryautomation.ClinicalLabAutoRecepient;
import cdac.medinfo.sdk.hl7282.hl7model.messages.clinicallaboratoryautomation.ClinicalLabAutoSource;
import cdac.medinfo.sdk.hl7282.hl7model.messages.financialmanagement.FinancialRecepient;
import cdac.medinfo.sdk.hl7282.hl7model.messages.financialmanagement.FinancialSource;
import cdac.medinfo.sdk.hl7282.hl7model.messages.masterfiles.MasterFileRecepient;
import cdac.medinfo.sdk.hl7282.hl7model.messages.masterfiles.MasterFileSource;
import cdac.medinfo.sdk.hl7282.hl7model.messages.medicalrecords.MediRecRecepient;
import cdac.medinfo.sdk.hl7282.hl7model.messages.medicalrecords.MediRecSource;
import cdac.medinfo.sdk.hl7282.hl7model.messages.observationreporting.ObsvRepRecepient;
import cdac.medinfo.sdk.hl7282.hl7model.messages.observationreporting.ObsvRepSource;
import cdac.medinfo.sdk.hl7282.hl7model.messages.orderentry.OrderEntryRecepient;
import cdac.medinfo.sdk.hl7282.hl7model.messages.orderentry.OrderEntrySource;
import cdac.medinfo.sdk.hl7282.hl7model.messages.patientadministration.ADTRecepient;
import cdac.medinfo.sdk.hl7282.hl7model.messages.patientadministration.ADTSource;
import cdac.medinfo.sdk.hl7282.hl7model.messages.patientcare.PatientCareRecepient;
import cdac.medinfo.sdk.hl7282.hl7model.messages.patientcare.PatientCareSource;
import cdac.medinfo.sdk.hl7282.hl7model.messages.patientreferral.PatientRefRecepient;
import cdac.medinfo.sdk.hl7282.hl7model.messages.patientreferral.PatientRefSource;
import cdac.medinfo.sdk.hl7282.hl7model.messages.personnelmanagement.PersonalMgmtRecepient;
import cdac.medinfo.sdk.hl7282.hl7model.messages.personnelmanagement.PersonalMgmtSource;
import cdac.medinfo.sdk.hl7282.hl7model.messages.query.QryRecepient;
import cdac.medinfo.sdk.hl7282.hl7model.messages.query.QrySource;
import cdac.medinfo.sdk.hl7282.hl7model.messages.scheduling.SchedulingRecepient;
import cdac.medinfo.sdk.hl7282.hl7model.messages.scheduling.SchedulingSource;
import cdac.medinfo.sdk.hl7282.utils.HL7Config;

/**
 * This class acts as main class for HL7MessageValidate Utility tool of HL7.
 * It validate the HL7 message file according to specified mode.
 */
public class HL7MessageValidate 
{
	static int lengthOfOption = 18;
	static int lengthOfDetails = 80 - lengthOfOption;

	public static void main(String[] args)
	{
		String strLoggingPath = null;

		HL7MessageValidate objHL7MessageValidate = new HL7MessageValidate();

		String strHL7File = null;

	
		/*
		 * If no parameters are provided then display the help.
		 */
		if(args == null || args.length ==0)
		{
			objHL7MessageValidate.displayHelp();
			System.exit(0);
		}

		/*
		 * This loop initializes the service parameters from the arguments provided.
		 */
		for(int i=0; i<args.length; i++)
		{
			//logging path.
			if(args[i].equalsIgnoreCase("-d") && args.length > i+1)
			{
				strLoggingPath = args[i+1];
				i++;
			}

			//HL7 File
			else if(args[i].equalsIgnoreCase("-f") && args.length > i+1)
			{
				strHL7File = args[i+1] ;
				i++;
			}
			else
			{
				System.out.println("Not a valid command");
				objHL7MessageValidate.displayHelp();
				System.exit(0);
			}
		}

		if(strHL7File == null)
		{
			System.out.println("Not a valid command");
			objHL7MessageValidate.displayHelp();
			System.exit(0);
		}

		try
		{
			HL7Config objHL7Config = HL7Config.createInstance();

			//Specifying logging directory.
			//User can specify any directory where log files will be created.
			//If no path is specified then logs will be generated in user's temp directory.
			objHL7Config.enableLogging(strLoggingPath);

			if(objHL7MessageValidate.Validate(strHL7File))
				System.out.println("Given file is valid HL7 file ");
			else
				System.out.println("Given file is not a valid HL7 file ");
		}
		catch(Exception e)
		{
			System.out.println("Given file is not a valid HL7 file ");
		}

	}

	/**
	 * Validates the HL7 message file
	 * @param strHL7File String value of HL7 message File Path
	 * @return True - if validation is successful. 
	 * @throws IOException throws I/O Exception if parsing failed
	 * @throws InvalidMessageException throws Invalid Message Exception if validation fails.
	 */
	private boolean Validate(String strHL7File)throws IOException, InvalidMessageException
	{
		HL7MessageValidator objMessageValidator = new HL7MessageValidator();
		objMessageValidator.setMessageFactory(getMessageFactory());
		
		if(objMessageValidator.validate(strHL7File))
			return true;
		else
			return false;
	}

	/*
	 * This function displays the help.
	 */
	private void displayHelp()
	{
		//Discription of command
		System.out.println("\nHL7MESSAGEVALIDATOR :: Validates HL7 message file ");

		//Signature
		System.out.println("\n" + "HL7MESSAGEVALIDATOR [-d LogDir]  " +
				"-f HL7File \n " + "\n");

		//Log directory
		printToConsole("-d", "Log directory");
		printToConsole("", "User's temp directory is taken as default.");

		//HL7 Files
		printToConsole("-f", "HL7 File which is to be validated.");
	
        
        System.out.println("\nExample :");

		//Example
		System.out.println("\n1. HL7MESSAGEVALIDATOR  -f message.hl7" +
		"\nValidates message.hl7 file in strict mode.\n");

	}

	/**
	 * Display Help of command on console in proper manner.
	 * @param strOption Option for command.
	 * @param strDetails Description of option.
	 */
	public static void printToConsole(String strOption, String strDetails)
	{
		String strBuffer = "";
		if (strOption != null)
			strBuffer = strBuffer + strOption ;
		while (lengthOfOption > strBuffer.length())
		{
			strBuffer = strBuffer + " ";
		}
		if (strDetails != null)
		{
			if (strDetails.length() < lengthOfDetails || strDetails.length() == lengthOfDetails)
			{
				strBuffer = strBuffer + strDetails;
				strDetails = null;
			}
			else
			{
				strBuffer = strBuffer + strDetails.substring(0, lengthOfDetails);
				strDetails = strDetails.substring(lengthOfDetails, (strDetails.length() ));
			}
		}

		System.out.println(strBuffer);
		if (strDetails == null)
			return;
		else
			printToConsole(null, strDetails);
	}

	/**
	 * Displays Help of command on console in proper manner.
	 * @param strAttribute Attribute for option.
	 * @param strDesc Description of attributes.
	 */
	public static void printToConsole(String strAttribute, String[] strDesc)
	{
		if (strDesc.length > 1)
			printToConsole(strAttribute, strDesc[0]);
		for(int i = 1;i<strDesc.length;i++)
			printToConsole(null, strDesc[i]);
	}

	/**
	 * Adds all system's Source and Recipient to MessageFactory.
	 */
	private MessageFactory getMessageFactory()
	{
		MessageFactory objMessageFactory = MessageFactory.createInstance();
		objMessageFactory.addMessageSource(new ObsvRepSource());
		objMessageFactory.addMessageRecepient(new ObsvRepRecepient());
		objMessageFactory.addMessageSource(new AppMgtSource());
		objMessageFactory.addMessageRecepient(new AppMgtRecepient());
		objMessageFactory.addMessageSource(new ClinicalLabAutoSource());
		objMessageFactory.addMessageRecepient(new ClinicalLabAutoRecepient());
		objMessageFactory.addMessageSource(new FinancialSource());
		objMessageFactory.addMessageRecepient(new FinancialRecepient());
		objMessageFactory.addMessageSource(new MasterFileSource());
		objMessageFactory.addMessageRecepient(new MasterFileRecepient());
		objMessageFactory.addMessageSource(new MediRecSource());
		objMessageFactory.addMessageRecepient(new MediRecRecepient());
		objMessageFactory.addMessageSource(new OrderEntrySource());
		objMessageFactory.addMessageRecepient(new OrderEntryRecepient());
		objMessageFactory.addMessageSource(new ADTSource());
		objMessageFactory.addMessageRecepient(new ADTRecepient());
		objMessageFactory.addMessageSource(new PatientCareSource());
		objMessageFactory.addMessageRecepient(new PatientCareRecepient());
		objMessageFactory.addMessageSource(new PatientRefSource());
		objMessageFactory.addMessageRecepient(new PatientRefRecepient());
		objMessageFactory.addMessageSource(new PersonalMgmtSource());
		objMessageFactory.addMessageRecepient(new PersonalMgmtRecepient());
		objMessageFactory.addMessageSource(new QrySource());
		objMessageFactory.addMessageRecepient(new QryRecepient());
		objMessageFactory.addMessageSource(new SchedulingSource());
		objMessageFactory.addMessageRecepient(new SchedulingRecepient());
		
		return objMessageFactory;
	}
}
