/*******************************************************************************
 * Copyright 2014 Centre for Development of Advanced Computing(C-DAC), Pune
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ******************************************************************************/
package in.cdac.medinfo.csnotk.csnolib.test;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import in.cdac.medinfo.csnotk.csnolib.agents.SNOMEDAgent;
import in.cdac.medinfo.csnotk.csnolib.commons.ConceptDetails;
import in.cdac.medinfo.csnotk.csnolib.commons.EnumDirection;
import in.cdac.medinfo.csnotk.csnolib.commons.EnumLangRefset;
import in.cdac.medinfo.csnotk.csnolib.model.CompositeDescription;
import in.cdac.medinfo.csnotk.csnolib.model.Concept;
import in.cdac.medinfo.csnotk.csnolib.model.Relationship;
//Logs
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import in.cdac.medinfo.csnotk.csnolib.util.LoggerUtility;

/**
 * SampleforLookupAPI class contains the sample code for implementing the lookup
 * APIs.
 */
public class SNOMEDAgentLookupAPI {

	/**
	 * Main method
	 *
	 * @param args
	 */
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		SNOMEDAgent agent = new SNOMEDAgent();
		agent.init();
        Logger logger = LogManager.getLogger(SNOMEDAgentLookupAPI.class);
		logger.info(LoggerUtility.CONSOLE, "Do you want to create SNOMED CT database (y/n)");
		BufferedReader serviceInput = new BufferedReader(
				new InputStreamReader(System.in));
		try {
			String dbOverride = serviceInput.readLine();
			if(dbOverride.equalsIgnoreCase("y"))
			{
				logger.info(LoggerUtility.CONSOLE, "Please Enter SNOMED CT Release file path till Snapshot");
				String snomedDirPath=serviceInput.readLine();
				boolean check=agent.createSNOMEDdb(snomedDirPath, true);
				if(check){
					logger.info(LoggerUtility.CONSOLE, "Do you want to create SNOMED CT Refset database (y/n)");
					String refsetDbOverride = serviceInput.readLine();
					if(refsetDbOverride.equalsIgnoreCase("y"))
					{
						agent.createSNOMEDRefsetdb(snomedDirPath, true);
					}
				}
			}
		} catch (IOException e1) {
			//Log the Exception
			logger.error(LoggerUtility.Exception, LoggerUtility.createErrorMessage(e1));
		}

	logger.info(LoggerUtility.CONSOLE, "Do you want to create SNOMED CT Extension database (y/n)");

		try {
			String dbOverride = serviceInput.readLine();
			if(dbOverride.equalsIgnoreCase("y"))
			{
				logger.info(LoggerUtility.CONSOLE, "Please Enter SNOMED CT Extension Release directory path till Snapshot");
				String snomedExtDirPath=serviceInput.readLine();
				agent.createExtensiondb(snomedExtDirPath, true);
			}
		} catch (IOException e1) {
			//Log the Exception
			logger.error(LoggerUtility.Exception, LoggerUtility.createErrorMessage(e1));
		}

		logger.info(LoggerUtility.CONSOLE, "Sample for Lookup API. Please select the "
				+ "service you want to use\n1.Lookup for Concept\n"
				+ "2.Lookup for Relationship\n"
				+ "Please enter any of the above options:");
		try {


			// converts the user input to integer value
			int sInput = Integer.parseInt(serviceInput.readLine());


			logger.info(LoggerUtility.CONSOLE, "Please enter Concept Id:");
			/**
			 * conceptIdinput takes value of Concept Id from the user
			 */
			BufferedReader conceptIdinput = new BufferedReader(
					new InputStreamReader(System.in));
			/**
			 * conceptId refers to Id of a particular SNOMED CT Concept
			 */
			String conceptId = conceptIdinput.readLine().trim();// "243120004";

			switch (sInput) {

			/*
			 * LOOKUP BY CONCEPT API
			 */

			case 1: {
				logger.info(LoggerUtility.CONSOLE, "Parameter: langrefset\n"
						+ "refers to the Language code for selection "
						+ "language as english of US, UK, HI or ALL "
						+ "Possible values are as follows-\n" + "[us, uk, hi, all]"
						+ " \nPlease enter language refset:");

				/**
				 * langrefsetInput takes input for langrefset value
				 */

				BufferedReader langrefsetInput = new BufferedReader(
						new InputStreamReader(System.in));
				/**
				 * langRefset refers to the language refset [US, UK, HI or ALL] from
				 * which the concept details are to be fetched.
				 */
				EnumLangRefset langRefset = EnumLangRefset
						.getEnum(langrefsetInput.readLine());
				/**
				 * getConceptDetails method retrieves the concept details
				 * associated with a given Concept identifier (corresponding
				 * descriptions and relationships are also listed)
				 */
				ConceptDetails conceptDetails = agent.getConceptDetails(
						conceptId, langRefset);



				// Checks if result object is null or not
				if(null == conceptDetails){
					logger.info(LoggerUtility.CONSOLE, "No result for provided Concept ID");
					break;
				}

				// Prints the details of the particular Concept Id
				logger.info(LoggerUtility.CONSOLE, "Concept Id:{}, FSN:{}, Definition status:{}, Active Status:{}"
						, conceptDetails.getConceptId()
						, conceptDetails.getFsn()
						, conceptDetails.getDefinitionStatus()
						, conceptDetails.isActive());

				// Prints the list of Descriptions corresponding to that concept
				logger.info(LoggerUtility.CONSOLE, "Descriptions:[ ");
				/**
				 * getDescriptions method returns a list of descriptions
				 * corresponding to the Concept.
				 */
				List<CompositeDescription> descriptions = conceptDetails.getDescriptions();

				for (CompositeDescription description : descriptions) {
					logger.info(LoggerUtility.CONSOLE, "{}-{}; ",description.getActiveStatus(),description.getTerm());

				}
				logger.info(LoggerUtility.CONSOLE, "]");
				logger.info(LoggerUtility.CONSOLE, "Size of Description : {}",descriptions.size());

				// Prints the list of Relationships associated with the concept
				logger.info(LoggerUtility.CONSOLE, "Relationships:");
				/**
				 * getRelationships method returns a list of Relationships
				 * corresponding to the Concept.
				 */
				List<Relationship> relConcepts = new ArrayList<Relationship>();
				relConcepts=conceptDetails.getRelationships();
				logger.info(LoggerUtility.CONSOLE, "Size of Related Concept : {}",relConcepts.size());
				for (Relationship relation : relConcepts) {
					logger.info(LoggerUtility.CONSOLE, "Type:{}; Destination Concept:Id: {}--{}{};"
							, relation.getType().getFullySpecifiedName()
							,relation.getDestinationConcept().getId(), relation.getDestinationConcept()
									.getFullySpecifiedName(),relation.getTime());
				}
				break;
			}
			case 2: {
				/*
				 * LOOKUP BY RELATIONSHIP API
				 */
				/**
				 * getConcept method creates an instance of Concept class.
				 */
				logger.info(LoggerUtility.CONSOLE, "Parameter: direction\n"
								+ "specifies the relationship direction i.e whether"
								+ " the specified concept Id is the source or destination."
								+ "Possible values : source, destination"
								+ " \nPlease enter direction:");
				/**
				 * dirInput takes input for direction of the relationship
				 */

				BufferedReader dirInput = new BufferedReader(
						new InputStreamReader(System.in));
				/**
				 * direction specifies the relationship direction i.e whether
				 * the specified concept Id is the source or destination.
				 */
				String direction = dirInput.readLine();

				/**
				 * lstRelations specifies the Set of Relationships returned by
				 * the lookup by relationship API.
				 */


				Set<Concept> relConcepts = new HashSet<Concept>();
				logger.info(LoggerUtility.CONSOLE, "Parameter: relation\n"
						+ "specifies the Relationship Type that"
						+ " needs to be searched for."
						+ "Possible values : is a, finding site,"
						+ " causative agent, has intent, procedure site, "
						+ "specimen substance, associated finding, "
						+ "associated with, associated morphology, "
						+ "has active ingredient "
						+ " \nPlease enter Relationship Type:");
				/**
				 * relationTypeInput specifies the Relationship Type
				 */

				BufferedReader relationTypeInput = new BufferedReader(
						new InputStreamReader(System.in));
				/**
				 * enumRelationshipType specifies the Relationship Type that
				 * needs to be searched for.
				 */
				String relationshipType = relationTypeInput.readLine();
			relConcepts=agent.getRelations(conceptId,relationshipType, EnumDirection.getEnum(direction.toLowerCase().trim()));
				logger.info(LoggerUtility.CONSOLE, "Related Concept ID's count : {}",relConcepts.size());
				if(null==relConcepts || relConcepts.size()==0){
					logger.info(LoggerUtility.CONSOLE, "No result for provided Concept ID and Relation");
					break;
				}

				// Prints the Concept Ids related to the Concept specified by
				// the user.
				logger.info(LoggerUtility.CONSOLE, "Related Concept Ids:");

					for (Concept rel : relConcepts) {
						logger.info(LoggerUtility.CONSOLE, "{}, FSN:{}",rel.getId(),rel.getFullySpecifiedName());
					}

				break;
			}
			default: {
				logger.info(LoggerUtility.CONSOLE, "Invalid option");
			}
			}

		} catch (Exception e) {
			logger.error(LoggerUtility.CONSOLE, LoggerUtility.createErrorMessage(e));
		}
	}
}
