package eu.dnetlib.data.objectstore.filesystem;

import java.io.*;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.nio.file.Path;
import javax.servlet.http.HttpServletResponse;

import eu.dnetlib.data.objectstore.rmi.ObjectStoreServiceException;
import eu.dnetlib.miscutils.datetime.HumanTime;
import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

/**
 * The Class ModularObjectStoreRESTService implement the controller REST of the object Store.
 */
@Controller
public class ModularObjectStoreRESTService {

	private static final Log log = LogFactory.getLog(ModularObjectStoreRESTService.class); // NOPMD by marko on 11/24/08 5:02 PM

	public static String retrieveURL(final String baseURI, final String basePath, final String objectStoreId, final String objectId)
			throws UnsupportedEncodingException {
		final StringBuilder sb = new StringBuilder(baseURI)
				.append("?objectStore=" + encode(objectStoreId))
				.append("&objectId=" + encode(objectId))
				.append("&basePath=" + encode(basePath));
		return sb.toString();
	}

	private static String encode(final String s) throws UnsupportedEncodingException {
		return URLEncoder.encode(s, "UTF-8");
	}

	/**
	 *
	 * @param res
	 * @param basePath
	 * @param objectStoreId
	 * @param objectId
	 * @throws IOException
	 * @throws ObjectStoreServiceException
	 */
	@RequestMapping(value = "/**/objectStore/retrieve.do")
	public void retrieve(final HttpServletResponse res,
			@RequestParam(value = "basePath", required = true) final String basePath,
			@RequestParam(value = "objectStore", required = true) final String objectStoreId,
			@RequestParam(value = "objectId", required = true) final String objectId) throws IOException, ObjectStoreServiceException {

		final long start = System.currentTimeMillis();
		final Path path = FileSystemUtility.objectStoreFilePath(basePath, objectStoreId, objectId);

		if (!Files.exists(path) || !Files.isReadable(path)) {
			final String msg = String.format("Object with identifier: %s not found the in %s", objectId, path);
			res.sendError(HttpServletResponse.SC_NOT_FOUND, msg);
			log.warn(msg);
		} else {
			try (final InputStream is = new BufferedInputStream(new FileInputStream(path.toFile()))) {

				final long size = Files.size(path);

				res.setHeader("Content-Length", String.valueOf(size));
				IOUtils.copyLarge(is, res.getOutputStream());

				if (log.isDebugEnabled()) {
					log.debug(String.format("retrive.do completed in %s, objId: %s", HumanTime.exactly(System.currentTimeMillis() - start), objectId));
				}
			} catch (IOException e) {
				final String msg = "unable to close input Stream";
				res.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, msg);
				log.error(msg, e);
			}
		}
	}
}
