package eu.dnetlib.openaire.action;

import java.io.StringWriter;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.List;

import eu.dnetlib.openaire.thrift.Project;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.log4j.Logger;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.runtime.RuntimeConstants;
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;

import eu.dnetlib.miscutils.datetime.DateUtils;
import eu.dnetlib.openaire.thrift.Author;

public class ActionUtils {

	private static Logger logger = Logger.getLogger(ActionUtils.class);

	public static String createResultProjectRelation(String source,
			String resultId, String projectType, String projectId)
			throws Exception {
		VelocityEngine ve = new VelocityEngine();
		ve.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath");
		ve.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName());
		ve.setProperty("runtime.log.logsystem.class", "org.apache.velocity.runtime.log.NullLogSystem");

		ve.init();

		Template t = ve.getTemplate("/eu/dnetlib/openaire/action/relation.vm");
		VelocityContext vc = new VelocityContext();

		List<Relation> rels = new ArrayList<Relation>();

		rels.add(createRelation(source, resultId, projectType, projectId));

		vc.put("relations", rels);

		StringWriter sw = new StringWriter();
		t.merge(vc, sw);

		return sw.toString();
	}

	// input id: 1306.3402
	// oai:arXiv.org:1306.3402
	// MD5("od________18::oai:arXiv.org:1306.3402")

    /**
     * Creates a new relation action.
     * @param source the result source. If not null, the resultId is transformed to openaire id. If null, the result is
     *               considered to be already an openaire result and is used verbatim
     * @param resultId the result id
     * @param projectType the project type. If not null, the projectId is transformed to openaire id. If null, the projectId is
     *               considered to be already in openaire format and is used verbatim
     * @param projectId the project id
     *
     * @return a relation
     */
	private static Relation createRelation(String source, String resultId,
			String projectType, String projectId) {
		String resultPrefix;
		String projectPrefix = null;

        if (source != null) {
            if (source.equals("arxiv")) {
                resultId = "oai:arXiv.org:" + resultId;
            } else if (source.equals("pubmed")) {
                resultId = "oai:europepmc.org:" + resultId;
            }

            resultPrefix = getPrefix(source);
            resultId = "50|" + getIdentifier(resultPrefix, resultId);
        }

        if (projectType != null) {
            if (projectType.equals("ec")) {
                projectPrefix = "corda_______";
            } else if (projectType.equals("wt")) {
                projectPrefix = "welcometrust";
            }

            projectId = projectPrefix + "::" + projectId;
        }

		return new Relation("resultProject", resultId, projectId);
	}
	
	public static String getPrefix(String source) {
		if (source.equals("doi")) {
			return "crossref____";
		} else if (source.equals("wos")) {
			return "webcrawl____";
		} else if (source.equals("arxiv")) {
			return "od________18";
		} else if (source.equals("openaire")) {
			return "openaire____";
		} else if (source.equals("pubmed")) {
			return "od_______908";
		} if (source.equals("orcid")) {
            return "crossref____";
        } if (source.equals("datacite")) {
            return "datacite____";
        } else if (source.equals("driver")) {
            return "driver______";
        } else
			return null;
	}

    public static String getSet(String source, String actionType) {
        if (source.equals("wos") || source.equals("arxiv") || source.equals("pubmed")) {
            if (actionType.equals("dmf"))
                return "iis-wos-entities";
            else if (actionType.equals("relation"))
                return "iis-referenced-projects";
        } else {
            if (actionType.equals("dmf"))
                return "userclaim_dmf";
            else if (actionType.equals("relation"))
                return "userclaim_result_project";
        }

        return null;
    }

    public static String getProvenance(String source) {
        if (source.equals("openaire"))
            return "user:claim:search";
        else if (source.equals("driver"))
            return "user:claim:search";
        else if (source.equals("doi"))
            return "user:claim:pid";
        else if (source.equals("wos") || source.equals("arxiv") || source.equals("pubmed"))
            return "sysimport:mining:repository";
        else
            return null;
    }

	public static String createDMF(String id, String source, String title,
			String description, String access_mode, String embargoEndDate,
			List<Author> authors, String url, String dcSource, String doi,
			List<Project> projects, List<String> subjects, List<String> concepts, String publicationDate, String publisher, String language, String category) throws Exception {

		VelocityEngine ve = new VelocityEngine();
		ve.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath");
		ve.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName());
		ve.setProperty("runtime.log.logsystem.class", "org.apache.velocity.runtime.log.NullLogSystem");
		ve.init();
		

		Template t = ve.getTemplate("/eu/dnetlib/openaire/action/dmf.vm");
		VelocityContext vc = new VelocityContext();

		String hostedby = null;
		String hostedbyName = null;
		String collectedFrom = null;
		String collectedFromName = null;
        String recordIdentifier = id;
		String prefix = getPrefix(source);

		if (source.equals("doi")) {
			hostedby = "openaire____::1256f046-bf1f-4afc-8b47-d0b147148b18";
			hostedbyName = "Unknown Repository";
			collectedFrom = "openaire____::crossref";
			collectedFromName = "Crossref";
			doi = id;
		} else if (source.equals("wos")) {
			hostedby = "openaire____::1256f046-bf1f-4afc-8b47-d0b147148b18";
			hostedbyName = "Unknown Repository";
			collectedFrom = "openaire____::webcrawl";
			collectedFromName = "Web Crawl";
		} else if (source.equals("arxiv")) {
            id = "oai:arXiv.org:" + id;
            recordIdentifier = id;
			hostedby = "opendoar____::18";
			hostedbyName = "arXiv.org e-Print Archive";
			collectedFrom = "opendoar____::18";
			collectedFromName = "arXiv.org e-Print Archive";
		} else if (source.equals("datacite")) {
            hostedby = "openaire____::datacite";
            hostedbyName = "Datacite";
            collectedFrom = "openaire____::datacite";
            collectedFromName = "Datacite";
        } else if (source.equals("orcid")) {
            hostedby = "openaire____::1256f046-bf1f-4afc-8b47-d0b147148b18";
            hostedbyName = "Unknown Repository";
            collectedFrom = "infospace___::crossref";
            collectedFromName = "Crossref";
            doi = id;
        } else if (source.equals("pubmed")) {
            id = "oai:europepmc.org:" + id;
            recordIdentifier = id;
            hostedby = "opendoar____::908";
            hostedbyName = "Europe PubMed Central";
            collectedFrom = "opendoar____::908";
            collectedFromName = "Europe PubMed Central";
        } else if (source.equals("driver")) {
            hostedby = "openaire____::1256f046-bf1f-4afc-8b47-d0b147148b18";
            hostedbyName = "Unknown Repository";
            collectedFrom = "openaire____::driver";
            collectedFromName = "Digital Repository Infrastructure Vision for European Research";
        }

        if (doi != null)
			vc.put("doi", doi);

        // openaire ids should not be touched!
        if (!source.equals("openaire"))
		    id = getIdentifier(prefix, id);

		vc.put("objIdentifier", id);
		vc.put("recordIdentifier", recordIdentifier);
		vc.put("dateOfCollection", DateUtils.calculate_ISO8601(System.currentTimeMillis()));
		vc.put("hostedby", hostedby);
		vc.put("collectedFrom", collectedFrom);
		vc.put("hostedbyName", hostedbyName);
		vc.put("collectedFromName", collectedFromName);

		vc.put("title", title);
		vc.put("description", description);
		vc.put("accessMode", access_mode);
		vc.put("dcSource", dcSource);
		vc.put("url", url);
		vc.put("publisher", publisher);
		vc.put("language", language);
		vc.put("objCategory", category);

		vc.put("datasourceprefix", prefix);

		List<String> creators = new ArrayList<String>();
		for (Author author : authors) {
            String name = author.getLastName();


            if (author.getFirstName() != null && !author.getFirstName().trim().isEmpty())
                name += ", " + author.getFirstName();

            creators.add(name);
		}

		vc.put("creators", creators);
		vc.put("projects", projects);
		vc.put("subjects", subjects);
        vc.put("concepts", concepts);
		
		if (publicationDate != null && !publicationDate.equals(""))
			vc.put("publicationDate", publicationDate + "-01-01T00:00:00Z");
		
		vc.put("StringEscapeUtils", StringEscapeUtils.class);

		StringWriter sw = new StringWriter();
		t.merge(vc, sw);
		
		return sw.toString();
	}

	// private static String getIdentifier(String prefix, String id) {
	// return prefix + "::" +
	// com.google.common.hash.Hashing.md5().hashString(id).toString();
	// }

	public static String getIdentifier(String prefix, String id) {
		try {
			MessageDigest md = MessageDigest.getInstance("MD5");

			md.update(id.getBytes("UTF-8"));

			return prefix + "::" + new String(org.apache.commons.codec.binary.Hex.encodeHex(md.digest()));
		} catch (Exception e) {
			logger.error("Error creating id", e);
			return null;
		}
	}

    public static void main(String[] args) throws  Exception {
        System.out.println(createRelation("pubmed", "662141", "ec", "sdfdf").getSourceId());
    }
}