/* Copyright (c) 2011 Peter Troshin
 *  
 *  JAva Bioinformatics Analysis Web Services (JABAWS) @version: 2.0     
 * 
 *  This library is free software; you can redistribute it and/or modify it under the terms of the
 *  Apache License version 2 as published by the Apache Software Foundation
 * 
 *  This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
 *  even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Apache 
 *  License for more details.
 * 
 *  A copy of the license is in apache_license.txt. It is also available here:
 * @see: http://www.apache.org/licenses/LICENSE-2.0.txt
 * 
 * Any republication or derived work distributed in source code form
 * must include this copyright and license notice.
 */

package compbio.ws.client;

import java.net.URL;
import java.util.Set;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;

import compbio.data.msa.JABAService;
import compbio.data.msa.MsaWS;
import compbio.data.msa.SequenceAnnotation;

/**
 * List of web services currently supported by JABAWS version 2.1
 * 
 */
public enum Services {
	/*
	 * Make sure this class has NO references to runners or engines as it is a
	 * part of minimal client package. Such things should go into ServicesUtil
	 */
	MafftWS, MuscleWS, ClustalWS, ClustalOWS, TcoffeeWS, ProbconsWS, MSAprobsWS, GLprobsWS,
	AAConWS, 
	JronnWS, DisemblWS, GlobPlotWS, IUPredWS, 
//	JpredWS,
	RNAalifoldWS;

	public static Services getService(String servName) {
		servName = servName.trim().toLowerCase();
		for (Services service : Services.values()) {
			if (service.toString().equalsIgnoreCase(servName)) {
				return service;
			}
		}
		return null;
	}

	Service getService(URL url, String sqname) {
		QName qname = new QName(sqname, this.toString());
		return Service.create(url, qname);
	}

	public String getJabawsVersion() {
		return JABAService.JABAWS_VERSION;
	}
	public static String toString(Set<Services> services) {
		if (services == null || services.isEmpty()) {
			return "No known services...\n";
		}
		String value = "";
		for (Services serv : services) {
			if (null != serv) {
				value += serv + "\n";
			} else {
				value += "Unknown Service\n";
			}
		}
		return value;
	}

	Class<? extends JABAService> getServiceType() {
		switch (this) {
			case AAConWS :
			case JronnWS :
			case DisemblWS :
			case GlobPlotWS :
			case IUPredWS :
			case RNAalifoldWS :
				return SequenceAnnotation.class;
//			case JpredWS :
			case ClustalWS :
			case ClustalOWS :
			case MafftWS :
			case MuscleWS :
			case ProbconsWS :
			case MSAprobsWS :
			case GLprobsWS :
			case TcoffeeWS :
				return MsaWS.class;
			default :
				throw new RuntimeException("Unrecognised Web Service Type " + this + " - Should never happen!");
		}
	}

	
	String getServiceNamespace() {
		switch (this) {
			case RNAalifoldWS :
			case AAConWS :
			case JronnWS :
			case DisemblWS :
			case GlobPlotWS :
			case IUPredWS :
			case MSAprobsWS :
			case GLprobsWS :
//			case JpredWS :
			case ClustalOWS :
				return JABAService.V2_SERVICE_NAMESPACE;
			case ClustalWS :
			case MafftWS :
			case MuscleWS :
			case ProbconsWS :
			case TcoffeeWS :
				return JABAService.SERVICE_NAMESPACE;
			default :
				throw new RuntimeException("Unrecognised JABAWS Namespace for service " + this +"!");
		}
	}
	
	JABAService getInterface(Service service) {
		assert service != null;

		QName portName = new QName(service.getServiceName().getNamespaceURI(), this.toString() + "Port");
		return service.getPort(portName, this.getServiceType());
	}

	public String getServiceInfo() {
		switch (this) {
			case AAConWS :
				return AACON_INFO.toString();
//			case JpredWS :
//				return JPRED_INFO.toString();
			case ClustalOWS :
				return CLUSTAL_OMEGA_INFO.toString();
			case ClustalWS :
				return CLUSTAL_INFO.toString();
			case DisemblWS :
				return DISEMBL_INFO.toString();
			case GlobPlotWS :
				return GLOBPLOT_INFO.toString();
			case IUPredWS :
				return IUPRED_INFO.toString();
			case JronnWS :
				return JRONN_INFO.toString();
			case MafftWS :
				return MAFFT_INFO.toString();
			case MuscleWS :
				return MUSCLE_INFO.toString();
			case ProbconsWS :
				return PROBCONS_INFO.toString();
			case MSAprobsWS :
				return MSAPROBS_INFO.toString();
			case GLprobsWS :
				return GLPROBS_INFO.toString();
			case TcoffeeWS :
				return TCOFFEE_INFO.toString();
			case RNAalifoldWS :
				return RNAALIFOLD_INFO.toString();
			default :
				throw new RuntimeException("Unrecognised Web Service Type " + this + " - Should never happen!");
		}
	}

	public String getServiceReference() {
		switch (this) {
			case AAConWS :
				return AACON_INFO.getReference();
//			case JpredWS :
//				return JPRED_INFO.getReference();
			case ClustalOWS :
				return CLUSTAL_OMEGA_INFO.getReference();
			case ClustalWS :
				return CLUSTAL_INFO.getReference();
			case DisemblWS :
				return DISEMBL_INFO.getReference();
			case GlobPlotWS :
				return GLOBPLOT_INFO.getReference();
			case IUPredWS :
				return IUPRED_INFO.getReference();
			case JronnWS :
				return JRONN_INFO.getReference();
			case MafftWS :
				return MAFFT_INFO.getReference();
			case MuscleWS :
				return MUSCLE_INFO.getReference();
			case ProbconsWS :
				return PROBCONS_INFO.getReference();
			case MSAprobsWS :
				return MSAPROBS_INFO.getReference();
			case GLprobsWS :
				return GLPROBS_INFO.getReference();
			case TcoffeeWS :
				return TCOFFEE_INFO.getReference();
			case RNAalifoldWS :
				return RNAALIFOLD_INFO.getReference();
			default :
				throw new RuntimeException("Unrecognised Web Service Type " + this + " - Should never happen!");
		}
	}

	public String getServiceVersion() {
		switch (this) {
			case AAConWS :
				return AACON_INFO.getVersion();
//			case JpredWS :
//				return JPRED_INFO.getVersion();
			case ClustalOWS :
				return CLUSTAL_OMEGA_INFO.getVersion();
			case ClustalWS :
				return CLUSTAL_INFO.getVersion();
			case DisemblWS :
				return DISEMBL_INFO.getVersion();
			case GlobPlotWS :
				return GLOBPLOT_INFO.getVersion();
			case IUPredWS :
				return IUPRED_INFO.getVersion();
			case JronnWS :
				return JRONN_INFO.getVersion();
			case MafftWS :
				return MAFFT_INFO.getVersion();
			case MuscleWS :
				return MUSCLE_INFO.getVersion();
			case ProbconsWS :
				return PROBCONS_INFO.getVersion();
			case MSAprobsWS :
				return MSAPROBS_INFO.getVersion();
			case GLprobsWS :
				return GLPROBS_INFO.getVersion();
			case TcoffeeWS :
				return TCOFFEE_INFO.getVersion();
			case RNAalifoldWS :
				return RNAALIFOLD_INFO.getVersion();
			default :
				throw new RuntimeException("Unrecognised Web Service Type " + this + " - Should never happen!");
		}
	}

	public String getServiceGroup() {
		switch (this) {
			case AAConWS :
				return "annotation";
//			case JpredWS :
//				return "annotation";
			case ClustalOWS :
				return "alignment";
			case ClustalWS :
				return "alignment";
			case DisemblWS :
				return "disorder";
			case GlobPlotWS :
				return "disorder";
			case IUPredWS :
				return "disorder";
			case JronnWS :
				return "disorder";
			case MafftWS :
				return "alignment";
			case MuscleWS :
				return "alignment";
			case ProbconsWS :
				return "alignment";
			case GLprobsWS :
				return "alignment";
			case MSAprobsWS :
				return "alignment";
			case TcoffeeWS :
				return "alignment";
			case RNAalifoldWS :
				return "annotation";
			default :
				throw new RuntimeException("Unrecognised Web Service Type " + this + " - Should never happen!");
		}
	}
	
	static ServiceInfo AACON_INFO = new ServiceInfo(AAConWS,
			"Peter V. Troshin, Agnieszka Golicz, David M. A. Martin, Fábio Madeira, James B. Procter and Geoffrey J. Barton\r\n" +
			"\"AACon: A Fast Amino Acid Conservation Calculation Service\"\r\n" +
			"(2017) Paper in preparation.",
			"1.1", "http://www.compbio.dundee.ac.uk/aacon");

//	static ServiceInfo JPRED_INFO = new ServiceInfo(JpredWS,
//			"Cole C, Barber JD, Barton GJ,\r\n" +
//			"\"The Jpred 3 secondary structure prediction server\"\r\n" +
//			"Nucl. Acids Res. 36 (suppl 2):W197 (2008)",
//			"3.0.3", "http://www.compbio.dundee.ac.uk/www-jpred");
	
	static ServiceInfo CLUSTAL_INFO = new ServiceInfo(ClustalWS,
			"Larkin MA, Blackshields G, Brown NP, Chenna R, McGettigan PA, McWilliam H, Valentin F, Wallace IM, Wilm A, Lopez R, Thompson JD, Gibson TJ, Higgins DG,\r\n" +
			"\"Clustal W and Clustal X version 2.0\"\r\n" + 
			"Bioinformatics, 23: 2947 (2007)",
			"2.1", "http://www.clustal.org/clustal2/");

	static ServiceInfo CLUSTAL_OMEGA_INFO = new ServiceInfo(ClustalOWS,
			"Sievers F, Wilm A, Dineen D, Gibson TJ, Karplus K, Li W, Lopez R, McWilliam H, Remmert M, Söding J, Thompson JD, Higgins DG,\r\n" +
			"\"Fast, scalable generation of high quality protein multiple sequence alignments using Clustal Omega\"\r\n" +
			"Mol Syst Biol. 7:539 (2011)",
			"1.2.4", "http://www.clustal.org/omega/");

	static ServiceInfo DISEMBL_INFO = new ServiceInfo(DisemblWS,
			"Linding R, Jensen LJ, Diella F, Bork P, Gibson TJ, and Russell RB,\r\n" +
			"\"Protein disorder prediction: implications for structural proteomics\"\r\n" +
			"Structure 11(11):1453 (2003)", 
			"1.5", "http://dis.embl.de/");

	static ServiceInfo GLOBPLOT_INFO = new ServiceInfo(GlobPlotWS,
			"Linding R, Russell RB, Neduva V and Gibson TJ,\r\n" +
			"GlobPlot: exploring protein sequences for globularity and disorder\r\n" + 
			"Nucl. Acids Res. 31 (13):3701 (2003)",
			"2.3", "http://globplot.embl.de/");

	static ServiceInfo IUPRED_INFO = new ServiceInfo(IUPredWS,
			"Dosztányi Z, Csizmók V, Tompa P, and Simon I,\r\n" +
			"\"The Pairwise Energy Content Estimated from Amino Acid Composition Discriminates between Folded and Intrinsically Unstructured Proteins\"\r\n" +
			"J. Mol. Biol. 347:827 (2005)", 
			"1.0", "http://iupred.enzim.hu/");

	static ServiceInfo TCOFFEE_INFO = new ServiceInfo(TcoffeeWS,
			"Notredame C, Higgins DG, Heringa L,\r\n" +
			"\"T-Coffee: A novel method for multiple sequence alignments\"\r\n" + 
			"JMB, 302(1):205 (2000)",
			"11.00.8cbe486", "http://tcoffee.crg.cat/apps/tcoffee/index.html");

	static ServiceInfo MUSCLE_INFO = new ServiceInfo(MuscleWS,
			"Edgar RC,\r\n"+ 
			"\"MUSCLE: multiple sequence alignment with high accuracy and high throughput\"\r\n" + 
			"Nucleic Acids Res. 32(5):1792 (2004)", 
			"3.8.31", "http://www.drive5.com/muscle/");

	static ServiceInfo PROBCONS_INFO = new ServiceInfo(ProbconsWS,
			"Do CB, Mahabhashyam MSP, Brudno M, and Batzoglou S,\r\n" +
			"\"PROBCONS: Probabilistic Consistency-based Multiple Sequence Alignment\"\r\n" + 
			"Genome Research 15:330 (2005)",
			"1.12", "http://probcons.stanford.edu/");

	static ServiceInfo MSAPROBS_INFO = new ServiceInfo(MSAprobsWS,
			"Liu Y, Schmidt B, and Maskell DL,\r\n" + 
			"\"MSAProbs: multiple sequence alignment based on pair hidden Markov models and partition function posterior probabilities\"\r\n" +
			"Bioinformatics, 26 (16):1958 (2010)",
			"0.9.7", "http://msaprobs.sourceforge.net/");

	static ServiceInfo GLPROBS_INFO = new ServiceInfo(GLprobsWS,
			"Yongtao Ye, Siu-Ming Yiu, David W. Cheung, Qing Zhan, Hing-Fung Ting, Yadong Wang, Tak-Wah Lam,\r\n" +
			"\"GLProbs: Aligning multiple sequences adaptively\"\r\n" + 
			"in progress (2013)",
			"1.0", "http://sourceforge.net/projects/glprobs/");

	static ServiceInfo JRONN_INFO = new ServiceInfo(JronnWS,
			"unpublished, original algorithm Yang ZR, Thomson R, McMeil P, and Esnouf RM,\r\n" + 
			"\"RONN: the bio-basis function neural network technique applied to the dectection of natively disordered regions in proteins\"\r\n" +
			"Bioinformatics 21:3369 (2005)\r\n",
			"1.0", "http://www.compbio.dundee.ac.uk/jabaws/");

	static ServiceInfo MAFFT_INFO = new ServiceInfo(MafftWS,
			"Katoh K, Toh H,\r\n" +
			"\"Parallelization of the MAFFT multiple sequence alignment program\"\r\n" + 
			"Bioinformatics 26:1899 (2010)",
			"7.310", "http://mafft.cbrc.jp/alignment/software/");

	static ServiceInfo RNAALIFOLD_INFO = new ServiceInfo(RNAalifoldWS,
			"Hofacker IL, Fekete M, and Stadler PV,\r\n"+ 
			"\"Secondary Structure Prediction for Aligned RNA Sequences\"\r\n" + 
			"J.Mol.Biol. 319:1059 (2002) and\r\n " + 
			"Bernhart SH, Hofacker IL Will S, Gruber AR, and Stadler PF,\r\n" + 
			"\"RNAalifold: Improved consensus structure prediction for RNA alignments\"\r\n" +
			"BMC Bioinformatics, 9:474 (2008)\r\n",
			"2.1.2", "http://www.tbi.univie.ac.at/RNA/");

	@XmlAccessorType(XmlAccessType.FIELD)
	static class ServiceInfo {
		Services service;
		String reference;
		String version;
		String moreinfo;
		final static String line_delimiter = "\n";

		private ServiceInfo() {
			// Default constructor for JAXB
		}
		private ServiceInfo(Services service, String reference, String version,
				String moreinfo) {
			this.service = service;
			this.reference = reference;
			this.version = version;
			this.moreinfo = moreinfo;
		}

		@Override
		public String toString() {
			String value = "SERVICE: " + service + " version " + version + line_delimiter + "\n";
			value += "JABAWS v. " + JABAService.JABAWS_VERSION + line_delimiter;
			value += "REFERENCE: " + reference + line_delimiter + "\n";
			value += "MORE INFORMATION: " + moreinfo + line_delimiter;
			return value;
		}

		public String getReference() {
			return "REFERENCE: " + reference + line_delimiter + "<br>MORE INFORMATION: " + moreinfo + line_delimiter;
		}

		public String getVersion() {
			return version;
		}
	}

	public static void main(String[] args) {
		System.out.println(MUSCLE_INFO);
	}
}
