package eu.dnetlib.data.objectstore.modular.inspector;

import static eu.dnetlib.miscutils.collections.MappedCollection.listMap;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import com.google.gson.Gson;

import eu.dnetlib.data.objectstore.modular.connector.ObjectStore;
import eu.dnetlib.data.objectstore.modular.connector.ObjectStoreDao;
import eu.dnetlib.data.objectstore.rmi.ObjectStoreFile;
import eu.dnetlib.data.objectstore.rmi.ObjectStoreServiceException;
import eu.dnetlib.enabling.inspector.AbstractInspectorController;
import eu.dnetlib.enabling.resultset.ResultSetListener;
import eu.dnetlib.miscutils.collections.MappedCollection;
import eu.dnetlib.miscutils.functional.UnaryFunction;

/**
 * The Class ObjectStoreInspector is the inspector controller of the objectStore.
 */
@Controller
public class ObjectStoreInspector extends AbstractInspectorController {

	// private static final Log log = LogFactory.getLog(ObjectStoreInspector.class);

	/** The object store dao. */
	@Autowired
	private ObjectStoreDao objectStoreDao;

	/**
	 * The Class ObjectStoreDescription.
	 */
	class ObjectStoreDescription {

		/** The id. */
		private String id;

		/** The size. */
		private int size;

		/**
		 * Instantiates a new object store description.
		 *
		 * @param id
		 *            the id
		 * @param size
		 *            the size
		 */
		public ObjectStoreDescription(final String id, final int size) {

			this.id = id;
			this.size = size;
		}

		/**
		 * Gets the interpretation.
		 *
		 * @return the interpretation
		 * @throws ObjectStoreServiceException
		 */
		public String getInterpretation() throws ObjectStoreServiceException {

			ObjectStore objectStore = objectStoreDao.getObjectStore(id);
			return objectStore.getInterpretation();
		}

		/**
		 * Gets the id.
		 *
		 * @return the id
		 */
		public String getId() {
			return id;
		}

		/**
		 * Sets the id.
		 *
		 * @param id
		 *            the new id
		 */
		public void setId(final String id) {
			this.id = id;
		}

		/**
		 * Gets the size.
		 *
		 * @return the size
		 */
		public int getSize() {
			return size;
		}

		/**
		 * Sets the size.
		 *
		 * @param size
		 *            the new size
		 */
		public void setSize(final int size) {
			this.size = size;
		}
	}

	/**
	 * Object stores.
	 *
	 * @param model
	 *            the model
	 */
	@RequestMapping(value = "/inspector/objectstores.do")
	public void objectStores(final Model model) {
		List<String> objectStores = objectStoreDao.listObjectStores();
		model.addAttribute("objectstores", MappedCollection.listMap(objectStores, new UnaryFunction<ObjectStoreDescription, String>() {

			@Override
			public ObjectStoreDescription evaluate(final String id) {
				try {
					ObjectStore objStore = objectStoreDao.getObjectStore(id);
					return new ObjectStoreDescription(id, objStore.getSize());
				} catch (ObjectStoreServiceException e) {
					return null;
				}
			}
		}));
	}

	/**
	 * Object store.
	 *
	 * @param model
	 *            the model
	 * @param id
	 *            the id
	 * @param startParam
	 *            the start param
	 * @param regex
	 *            the regex
	 * @throws ObjectStoreServiceException
	 */
	@RequestMapping(value = "/inspector/objectstore.do", method = RequestMethod.GET)
	public void objectStore(final Model model,
			@RequestParam("id") final String id,
			@RequestParam(value = "start", required = false) final Integer startParam,
			@RequestParam(value = "regex", required = false) final String regex) throws ObjectStoreServiceException {
		int pageSize = 10;
		int start = 0;

		if (startParam != null) {
			start = startParam;
		}
		ObjectStore objctStore = objectStoreDao.getObjectStore(id);
		ResultSetListener rs = objctStore.deliver((long) 0, System.currentTimeMillis());
		List<String> page = rs.getResult((1 + start), (start + pageSize));
		final Gson g = new Gson();
		model.addAttribute("id", id);
		model.addAttribute("start", start);
		model.addAttribute("regex", regex);
		model.addAttribute("nextPage", start + pageSize);
		model.addAttribute("prevPage", Math.max(0, start - pageSize));
		model.addAttribute("size", rs.getSize());
		model.addAttribute("page", listMap(page, new UnaryFunction<ObjectStoreFile, String>() {

			@Override
			public ObjectStoreFile evaluate(final String json) {
				return g.fromJson(json, ObjectStoreFile.class);
			}
		}));

	}

	/**
	 * Gets the object store dao.
	 *
	 * @return the object store dao
	 */
	public ObjectStoreDao getObjectStoreDao() {
		return objectStoreDao;
	}

	/**
	 * Sets the object store dao.
	 *
	 * @param objectStoreDao
	 *            the new object store dao
	 */
	public void setObjectStoreDao(final ObjectStoreDao objectStoreDao) {
		this.objectStoreDao = objectStoreDao;
	}

}
