package eu.dnetlib.enabling.aas.nh;

import java.io.StringReader;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.apache.log4j.Logger;
import org.springframework.util.StringUtils;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import eu.dnetlib.enabling.aas.is.ISServicesVersionHolder;


/**
 * Notification utilities.
 * @author mhorst
 *
 */
public class NotificationUtils {

	protected static final Logger log = Logger.getLogger(NotificationUtils.class);
	
	public static final boolean isNewVersionByDefault 	= true;
	public static final String minorVersionDiff 		= "1.1.0"; 
	
	public static final String XML_ELEMENT_RESOURCE_TYPE 		= "RESOURCE_TYPE";
	public static final String XML_ELEMENT_RESOURCE_IDENTIFIER 	= "RESOURCE_IDENTIFIER";
	static final char topicRegistrationDelimiter 				= '/';
	
	/**
	 * Extracts resource type from profile content.
	 * @param profileContent
	 * @return resource type
	 */
	public static String extractResourceType(String profileContent) {
		if (profileContent==null)
			return null;
		try {
			ProfileHandler handler = new ProfileHandler();
			SAXParserFactory factory = SAXParserFactory.newInstance();
			SAXParser parser = factory.newSAXParser();
			parser.parse(new InputSource(new StringReader(profileContent)), handler);
			return handler.resourceType;
		} catch (Exception e) {
			log.error("Exception occured when parsing profileContent: " + profileContent, e);
			return null;
		}
	}
	
	/**
	 * Extracts profId from profile content.
	 * @param profileContent
	 * @return profId
	 */
	public static String extractProfId(String profileContent) {
		if (profileContent==null)
			return null;
		try {
			ProfileHandler handler = new ProfileHandler();
			SAXParserFactory factory = SAXParserFactory.newInstance();
			SAXParser parser = factory.newSAXParser();
			parser.parse(new InputSource(new StringReader(profileContent)), handler);
			return handler.profId;
		} catch (Exception e) {
			log.error("Exception occured when parsing profileContent: " + profileContent, e);
			return null;
		}
	}
	
	/**
	 * Builds topic for given topic type, resource type and profile id according to issnVersion.
	 * @param topicType
	 * @param resourceType
	 * @param profId
	 * @param issnVersion
	 * @return topic 
	 */
	public static String buildTopicForProfId(String topicType, String resourceType, 
			String profId, String issnVersion) {
		return (NotificationUtils.isNewISSNVersion(issnVersion)?
						NotificationUtils.buildTopicForProfId_new_version(topicType, resourceType, profId)
								:buildTopicForProfId_1_0_1_version(topicType, profId));
	}
	
	/**
	 * Builds topic for given topic type and profile id.
	 * This method is ISSN 1.0.1 version compliant.
	 * @param topicType
	 * @param profId
	 * @return topic
	 */
	private static String buildTopicForProfId_1_0_1_version(String topicType, String profId) {
		return topicType + topicRegistrationDelimiter + profId;
	}
	
	/**
	 * Builds topic for given topic type, resource type and profile id.
	 * This method is ISSN 1.1.0 version and above compliant.
	 * @param topicType
	 * @param resourceType
	 * @param profId
	 * @return topic 
	 */
	private static String buildTopicForProfId_new_version(String topicType, String resourceType, 
			String profId) {
		return topicType + topicRegistrationDelimiter + 
			resourceType + topicRegistrationDelimiter + profId;
	}
	
	/**
	 * Checks if issnVersion given as parameter is a new ISSN version.
	 * @param issnVersion
	 * @return
	 */
	public static boolean isNewISSNVersion(String issnVersion) {
		if (issnVersion==null) {
			log.debug("null issnVersion received, new ISSN version set by default = "+
					isNewVersionByDefault);
			return isNewVersionByDefault;
		}
		String[] tokens = StringUtils.tokenizeToStringArray(issnVersion, 
				ISServicesVersionHolder.SERVICE_VERSION_TOKEN_DELIMITER);
		if (tokens==null || tokens.length<3) {
			log.debug("bad issnVersion received: "+issnVersion+
					", new ISSN version set by default = "+isNewVersionByDefault);
			return isNewVersionByDefault;
		}
		String minorVersionToken = tokens[2];
		if (minorVersionToken==null) {
			log.debug("bad issnVersion received: "+issnVersion+
					", new ISSN version set by default = "+isNewVersionByDefault);
			return isNewVersionByDefault;
		}
//		lex string comparison
		if (minorVersionToken.compareTo(minorVersionDiff)<0)
			return false;
		else
			return true;
	}
}


class ProfileHandler extends DefaultHandler {
	
	String resourceType = null;
	String profId = null;
	
	@Override
	public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
		if (qName.equals(NotificationUtils.XML_ELEMENT_RESOURCE_TYPE)) {
			resourceType = attributes.getValue("", "value");
		}
		if (qName.equals(NotificationUtils.XML_ELEMENT_RESOURCE_IDENTIFIER)) {
			profId = attributes.getValue("", "value");
		}
	}
	
}
