package eu.dnetlib.enabling.annotations;

import com.google.gson.Gson;

import eu.dnetlib.enabling.datastructures.AbstractXmlResource;
import eu.dnetlib.rmi.objects.is.DnetResourceType;
import eu.dnetlib.rmi.soap.exceptions.InformationServiceException;

public class DnetResourceHelper {

	public static boolean isDnetResource(final Class<?> clazz) {
		return clazz.isAnnotationPresent(DnetResource.class);
	}

	public static boolean isDnetResource(final Object o) {
		return isDnetResource(o.getClass());
	}

	public static final DnetResourceType obtainResourceType(final Class<?> clazz) throws InformationServiceException {
		if (isDnetResource(clazz)) {
			final DnetResource a = clazz.getAnnotation(DnetResource.class);
			return new DnetResourceType(a.type(), a.kind(), a.format());
		} else {
			throw new InformationServiceException("Class " + clazz + " is not a DnetResource (missing annotation)");
		}
	}

	public static final DnetResourceType obtainResourceType(final Object o) throws InformationServiceException {
		return obtainResourceType(o.getClass());
	}

	public static final String convertToString(final Object o) throws InformationServiceException {
		if (isDnetResource(o)) {
			final DnetResource a = o.getClass().getAnnotation(DnetResource.class);
			switch (a.format()) {
			case JSON:
				return new Gson().toJson(o);
			case XML:
				if (o instanceof AbstractXmlResource) {
					return ((AbstractXmlResource) o).asXML();
				} else {
					throw new InformationServiceException("Class " + o.getClass().getName() + " not extends AbstractXmlResource");
				}
			case TEXT:
				return o.toString();
			default:
				throw new InformationServiceException("Invalid format " + a.format());
			}
		} else {
			throw new InformationServiceException("Object of " + o.getClass() + " is not a DnetResource (missing annotation)");
		}
	}

	public static final <T> T convertToObject(final String s, final Class<T> clazz) throws InformationServiceException {
		if (isDnetResource(clazz)) {
			final DnetResource a = clazz.getAnnotation(DnetResource.class);
			switch (a.format()) {
			case JSON:
				return new Gson().fromJson(s, clazz);
			case XML:
				try {
					return clazz.getConstructor(String.class).newInstance(s);
				} catch (Throwable e) {
					throw new InformationServiceException("Cannot instantiate object of Class " + clazz.getName());
				}
			case TEXT:
				try {
					return clazz.getConstructor(String.class).newInstance(s);
				} catch (Throwable e) {
					throw new InformationServiceException("Cannot instantiate object of Class " + clazz.getName());
				}
			default:
				throw new InformationServiceException("Invalid format " + a.format());
			}
		} else {
			throw new InformationServiceException("Class" + clazz + " is not a DnetResource (missing annotation)");
		}
	}
}
