package eu.dnetlib.enabling.tools;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

import eu.dnetlib.enabling.is.sn.rmi.ISSNService;
import eu.dnetlib.enabling.is.store.rmi.ISStoreException;
import eu.dnetlib.enabling.is.store.rmi.ISStoreService;

/**
 * 
 * TODO: document. TODO: Too low level, why the interfacing the Store and not the Registry ?
 * 
 * @author michele
 * 
 */
public class ResourceType {

	/**
	 * xmldb collection where resource types are stored.
	 */
	public static final String RESOURCE_TYPES = "DRIVERResourceTypes";

	/**
	 * resource type. (Including kind?)
	 */
	private String resourceType; // NOPMD

	/**
	 * resource schema. (Body?)
	 */
	private String resourceSchema; // NOPMD
	/**
	 * file where a copy of the schema is stored locally TODO: why ?
	 */
	private File fileSchema;

	/**
	 * instanciate an already registered resource type, fetching it from the store.
	 * 
	 * @param resourceType
	 *            resourceType name
	 * @param store
	 *            store service where the type is stored
	 * @param basedir
	 *            base dir where a local copy is held (why?)
	 * @throws ISStoreException
	 *             happens
	 */
	public ResourceType(final String resourceType, final ISStoreService store, final String basedir) throws ISStoreException {
		this(resourceType, store.getXML(resourceType, RESOURCE_TYPES), basedir);
	}

	/**
	 * construct a resource type.
	 * 
	 * @param resourceType
	 *            resourceType name
	 * @param resourceSchema
	 *            resourceSchema xsd body
	 * @param basedir
	 *            base directory of some local copy (?)
	 * @throws ISStoreException
	 *             happens
	 */
	public ResourceType(final String resourceType, final String resourceSchema, final String basedir) throws ISStoreException {
		this.resourceType = resourceType;
		this.resourceSchema = resourceSchema;
		if (basedir != null)
			this.fileSchema = saveSchemaAsFile(basedir);
	}

	/**
	 * stores the schema on the xmldb.
	 * 
	 * @param store
	 *            store service
	 * @throws ISStoreException
	 *             happens
	 */
	public void store(final ISStoreService store) throws ISStoreException {
		store.insertXML(resourceType, RESOURCE_TYPES, resourceSchema);
	}

	/**
	 * updates the in memory resource instance from the store.
	 * 
	 * @param store store service
	 * @throws ISStoreException happens
	 */
	public void update(final ISStoreService store) throws ISStoreException {
		store.updateXML(resourceType, RESOURCE_TYPES, resourceSchema);
	}

	/**
	 * save the schema to a file.
	 * 
	 * @param basedir
	 *            base directory
	 * @return the newly created file
	 * @throws ISStoreException
	 *             happens, even if the file cannot be created.
	 */
	private File saveSchemaAsFile(final String basedir) throws ISStoreException {
		fileSchema = new File(basedir + "/" + resourceType);
		if (!fileSchema.exists()) {
			try {
				final BufferedWriter out = new BufferedWriter(new FileWriter(fileSchema));
				out.write(resourceSchema);
				out.close();
			} catch (IOException e) {
				throw new ISStoreException("Error saving file", e);
			}
		}
		return fileSchema;
	}

	/**
	 * it says "delete and notify" but it only deletes the schema from the filesystem and from the store.
	 * 
	 * TODO: document and possibly refactor.
	 * 
	 * @param store
	 *            store service
	 * @param issn
	 *            ISSN service
	 * @throws ISStoreException
	 *             happens
	 */
	public void deleteAndNotify(final ISStoreService store, final ISSNService issn) throws ISStoreException {
		fileSchema.delete();
		store.deleteXML(resourceType, RESOURCE_TYPES);
	}

	public String getResourceType() {
		return resourceType;
	}

	public void setResourceType(final String resourceType) {
		this.resourceType = resourceType;
	}

	public String getResourceSchema() {
		return resourceSchema;
	}

	public void setResourceSchema(final String resourceSchema) {
		this.resourceSchema = resourceSchema;
	}

	public File getFileSchema() {
		return fileSchema;
	}

	public void setFileSchema(final File fileSchema) {
		this.fileSchema = fileSchema;
	}

}
