/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


package org.apache.oodt.cas.curation.service;

//OODT imports
import org.apache.oodt.cas.curation.structs.ExtractorConfig;
import org.apache.oodt.cas.curation.util.CurationXmlStructFactory;
import org.apache.oodt.cas.curation.util.ExtractorConfigReader;
import org.apache.oodt.cas.filemgr.catalog.Catalog;
import org.apache.oodt.cas.filemgr.repository.XMLRepositoryManager;
import org.apache.oodt.cas.filemgr.structs.Product;
import org.apache.oodt.cas.filemgr.structs.ProductType;
import org.apache.oodt.cas.filemgr.structs.Reference;
import org.apache.oodt.cas.filemgr.structs.exceptions.CatalogException;
import org.apache.oodt.cas.filemgr.structs.exceptions.RepositoryManagerException;
import org.apache.oodt.cas.filemgr.util.GenericFileManagerObjectFactory;
import org.apache.oodt.cas.metadata.MetExtractor;
import org.apache.oodt.cas.metadata.Metadata;
import org.apache.oodt.cas.metadata.SerializableMetadata;
import org.apache.oodt.cas.metadata.exceptions.MetExtractionException;
import org.apache.oodt.cas.metadata.util.GenericMetadataObjectFactory;

//JDK imports
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.Iterator;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

//JAX-RS imports
import javax.ws.rs.DefaultValue;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.Consumes;

//JSON imports
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import net.sf.json.JSONSerializer;

@Path("metadata")
/**
 * 
 * A web-service endpoint for dealing with CAS {@link Metadata} object.
 * 
 * @author pramirez
 * @version $Id$
 */
public class MetadataResource extends CurationService {
  
  @Context
  UriInfo uriInfo;

  private static final long serialVersionUID = 1930946924218765724L;

  public static final String STAGING = "staging";

  public static final String CATALOG = "catalog";

  public static final String PRODUCT_TYPE = "productType";
  
  public MetadataResource(){
    
  }

  public MetadataResource(@Context ServletContext context) {

  }

  @GET
  @Path(STAGING)
  @Produces("text/plain")
  public String getStagingMetadata(@QueryParam("id") String id,
      @DefaultValue(FORMAT_HTML) @QueryParam("format") String format,
      @QueryParam("configId") String configId,
      @DefaultValue("false") @QueryParam("overwrite") Boolean overwrite,
      @Context HttpServletRequest req, @Context HttpServletResponse res) {
    
      // this.sendRedirect("login.jsp", uriInfo, res);

      Metadata metadata = null;
      
      try {
        metadata = this.getStagingMetadata(id, configId, overwrite);
      } catch (Exception e) {
        return "<div class=\"error\">" + e.getMessage() + "</div>";
      }
      
      if (FORMAT_HTML.equals(format)) {
        return this.getMetadataAsHTML(metadata);
      }
      return this.getMetadataAsJSON(metadata).toString();
  }
  
  @GET
  @Path("extractor/config")
  @Produces("text/plain")
  public String getMetExtractorConfigList(
      @DefaultValue("") @QueryParam("current") String current,
      @DefaultValue(FORMAT_HTML) @QueryParam("format") String format) {
    String[] configIds = this.getFilesInDirectory(this.config
        .getMetExtrConfUploadPath(), false);

    if (FORMAT_HTML.equals(format)) {
      return this.getExtractorConfigIdsAsHTML(configIds, current);
    }
    return this.getExtractorConfigIdsAsJSON(configIds);
  }

  protected String getExtractorConfigIdsAsHTML(String[] configIds,
      String current) {
    StringBuffer html = new StringBuffer();
    for (int i = 0; i < configIds.length; i++) {
      html.append("<option ");
      if (configIds[i].equals(current)) {
        html.append("selected ");
      }
      html.append("value=\"");
      html.append(configIds[i]);
      html.append("\">");
      html.append(configIds[i]);
      html.append("</option>\r\n");
    }
    return html.toString();
  }
  
  protected String getExtractorConfigIdsAsJSON(String[] configIds) {
    // TODO: Support JSON
    return "Not Implemented...";
  }

  /**
   * 
   * @param id
   *          Relative path from staging root to product. The met extension will
   *          be added to this id to look up and see if a met file exists with
   *          in the met area.
   * @param configId
   *          Reference to the extractor config. {@link ExtractorConfigReader}
   *          will load the configuration
   * @param overwrite
   *          Flag to indicate whether or not to overwrite a met file if present
   *          in the staging area.
   * @return The {@link Metadata} retrieved from the met area path if present or
   *         extracted using the met extractor config.
   * @throws FileNotFoundException
   * @throws InstantiationException
   * @throws IOException
   * @throws MetExtractionException
   */
  protected Metadata getStagingMetadata(String id, String configId,
      Boolean overwrite) throws FileNotFoundException, InstantiationException,
      IOException, MetExtractionException {
    if (configId == null || configId.trim().length() == 0) {
      return this.readMetFile(id + CurationService.config.getMetExtension());
    } else {
      String relMetPath = id.startsWith("/") ? id : "/" + id;
      String pathToMetFile = CurationService.config.getMetAreaPath()
          + relMetPath + CurationService.config.getMetExtension();
      if (!overwrite && new File(pathToMetFile).exists()) {
        return this.readMetFile(id + CurationService.config.getMetExtension());
      } else {
        // Make sure the parent directory exists
        new File(pathToMetFile).getParentFile().mkdirs();
        Metadata metadata = this.runMetExtractor(id, ExtractorConfigReader
            .readFromDirectory(
                new File(CurationService.config
                .getMetExtrConfUploadPath()), configId));
        this.writeMetFile(id, metadata);
        return metadata;
      }
    }
  }

  /**
   * 
   * @param id
   *          Relative path from staging root to the product
   * @param config
   *          Configuration to run this met extractor
   * @return
   * @throws MetExtractionException
   */
  protected Metadata runMetExtractor(String id, ExtractorConfig config)
      throws MetExtractionException {
    MetExtractor metExtractor = GenericMetadataObjectFactory
        .getMetExtractorFromClassName(config.getClassName());
    metExtractor.setConfigFile(config.getConfigFiles().get(0));
    return metExtractor.extractMetadata(CurationService.config
        .getStagingAreaPath()
        + "/" + id);
  }
  
  @GET
  @Path(CATALOG)
  @Produces("text/plain")
  public String getCatalogMetadata(@QueryParam("id") String id,
      @DefaultValue(FORMAT_HTML) @QueryParam("format") String format,
      @Context HttpServletRequest req, @Context HttpServletResponse res) {

      // this.sendRedirect("login.jsp", uriInfo, res);
      // Call file manager to get metadata
      Product prod;
      Metadata metadata;
      String productId = id.substring(id.lastIndexOf("/") + 1);

      try {
        prod = CurationService.config.getFileManagerClient().getProductById(
          productId);
        metadata = this.getCatalogMetadata(prod);
      } catch (Exception e) {
        return "<div class=\"error\">" + e.getMessage() + "</div>";
      }

      if (FORMAT_HTML.equals(format)) {
        return this.getMetadataAsHTML(metadata);
      }
      return this.getMetadataAsJSON(metadata).toString();
  }

  @POST
  @Path(CATALOG)
  @Consumes("application/x-www-form-urlencoded")
  @Produces("text/plain")
  public String setCatalogMetadata(MultivaluedMap<String, String> formParams,
      @FormParam("id") String id) {
    Product prod;
    Metadata metadata = this.getMetadataFromMap(formParams);
    
    //FIXME: when https://issues.apache.org/jira/browse/CXF-3274
    //is addressed
    if (id == null) id = formParams.getFirst("id");
    String productId = id.substring(id.lastIndexOf("/") + 1);

    try {
      prod = CurationService.config.getFileManagerClient().getProductById(
          productId);
      this.updateCatalogMetadata(prod, metadata);
    } catch (Exception e) {
      e.printStackTrace();
      return "<div class=\"error\">" + e.getMessage() + "</div>";
    }

    return this.getMetadataAsHTML(metadata);
  }
  
  @GET
  @Path(PRODUCT_TYPE)
  @Produces("text/plain")
  public String getProductTypeMetadata(@QueryParam("id") String id,
      @DefaultValue(FORMAT_HTML) @QueryParam("format") String format,
      @Context HttpServletRequest req, @Context HttpServletResponse res) {

    // this.sendRedirect("login.jsp", uriInfo, res);

    Metadata metadata;
    String[] idParts = id.split("/");
    String policy = idParts[1];
    String productType = idParts[2];
    try {
      metadata = getProductTypeMetadataForPolicy(policy, productType);
    } catch (Exception e) {
      return "<div class=\"error\">" + e.getMessage() + "</div>";
    }

    if (FORMAT_HTML.equals(format)) {
      return this.getMetadataAsHTML(metadata);
    }
    return this.getMetadataAsJSON(metadata).toString();
  }
  

  @POST
  @Path(PRODUCT_TYPE)
  @Consumes("application/x-www-form-urlencoded")
  @Produces("text/plain")
  public String setProductTypeMetadata(MultivaluedMap<String, String> formParams) {
    String[] idParts = formParams.getFirst("id").split("/");
    String policy = idParts[1];
    String productType = idParts[2];
    try {
    this.writeProductTypeMetadata(policy, productType, this
        .getMetadataFromMap(formParams));
    } catch (Exception e) {
      return "<div class=\"error\">" + e.getMessage() + "</div>";
    }
    return "";
  }

  @POST
  @Path(STAGING)
  @Consumes("application/x-www-form-urlencoded")
  @Produces("text/plain")
  public String setStagingMetadata(MultivaluedMap<String, String> formParams) {
    try {
      this.writeMetFile(formParams.getFirst("id"), this
          .getMetadataFromMap(formParams));
    } catch (Exception e) {
      return "<div class=\"error\">" + e.getMessage() + "</div>";
    }
    return "";
  }

  @GET
  @Path("staging/info")
  @Produces("text/plain")
  public String getMetadataInfo(@QueryParam("id") String id) {

      return "Staging met info";
  }
  

  private JSONObject getMetadataAsJSON(Metadata metadata) {
    return JSONObject.fromObject(metadata.getHashtable());
  }

  private Metadata getMetadataFromJSON(String metadataJSON) {
    JSONObject json = (JSONObject) JSONSerializer.toJSON(metadataJSON);
    Metadata metadata = new Metadata();

    Set<String> keys = json.keySet();
    for (String key : keys) {
      List values = (List) JSONSerializer.toJava((JSONArray) json.get(key));
      metadata.addMetadata(key, values);
    }

    return metadata;
  }
  
  private Metadata getMetadataFromMap(MultivaluedMap<String, String> formParams) {
    Metadata metadata = new Metadata();
    
    for (String key : formParams.keySet()) {
      if (key.startsWith("metadata.")) {
        String newKey = key.substring(key.indexOf('.') + 1);
        for (String value : formParams.get(key)) {
          metadata.addMetadata(newKey, value);
        }
      }
    }
    
    return metadata;
  }
  
  protected String getMetadataAsHTML(Metadata metadata) {
    if (metadata == null) {
      return "<table></table>";
    }

    StringBuffer html = new StringBuffer();

    html.append("<table>\r\n");
    for (String key : (Set<String>) metadata.getHashtable().keySet()) {
      html.append(" <tr>\r\n");
      html.append("  <th>").append(key).append("</th>\r\n");
      html.append("  <td class=\"").append(key).append("\">");
      List<String> values = metadata.getAllMetadata(key);
      for (Iterator<String> i = values.iterator(); i.hasNext();) {
        html.append("<span>").append(i.next()).append("</span>");
        if (i.hasNext()) {
          html.append(", ");
        }
      }
      for (String value : (List<String>) metadata.getAllMetadata(key)) {
      }
      html.append("</td>\r\n");
      html.append(" </tr>\r\n");
    }
    html.append("</table>\r\n");

    return html.toString();
  }
  

  /**
   * Reads a {@link Metadata} object from a String representation of a .met
   * {@link File}.
   * 
   * @param file
   *          The full path to the .met {@link File}.
   * @return The read-in CAS {@link Metadata} object.
   * @throws InstantiationException
   * @throws InstantiationException
   *           If there is an error instantiating the {@link Metadata} class.
   * @throws IOException
   * @throws FileNotFoundException
   * @throws FileNotFoundException
   *           If the .met {@link File} is not found.
   * @throws IOException
   *           If there is an IO problem opening the met file.
   */
  public Metadata readMetFile(String file) throws InstantiationException,
      FileNotFoundException, IOException {
    SerializableMetadata metadata = new SerializableMetadata("UTF-8", false);
    metadata.loadMetadataFromXmlStream(new FileInputStream(config
        .getMetAreaPath()
        + "/" + file));

    return metadata;
  }

  /**
   * Retrieves the cataloged {@link Metadata} associated with a {@link Product}.
   * 
   * @param product
   *          The {@link Product} to obtain cataloged {@link Metadata} for.
   * @return The cataloged {@link Metadata} for {@link Product}.
   * @throws CatalogException
   *           If there is an error talking to the CAS File Manager
   *           {@link Catalog}.
   */
  public Metadata getCatalogMetadata(Product product) throws CatalogException {
    return CurationService.config.getFileManagerClient().getMetadata(
        CurationService.config.getFileManagerClient().getProductById(
            product.getProductId()));
  }

  /**
   * Writes a CAS {@link Metadata} {@link File} using the given identifier.
   * 
   * @param id
   *          The identifier of the .met file to write.
   * @param metadata
   *          The {@link Metadata} object to persist and write to a {@link File}
   *          .
   * @throws FileNotFoundException
   *           If the .met {@link File} cannot be written.
   * @throws IOException
   *           If there is an IO exception writing the {@link File}.
   */
  public void writeMetFile(String id, Metadata metadata)
      throws FileNotFoundException, IOException {
    SerializableMetadata serMet = new SerializableMetadata(metadata, "UTF-8",
        false);
    serMet.writeMetadataToXmlStream(new FileOutputStream(new File(config
        .getMetAreaPath(), id + config.getMetExtension())));
  }

  /**
   * Updates the cataloged {@link Metadata} for a {@link Product} in the CAS
   * File Manager.
   * 
   * @param product
   *          The {@link Product} to update {@link Metadata} for.
   * @param metadata
   *          The new {@link Metadata} to persist into the {@link Catalog}.
   * @throws CatalogException
   *           If any error occurs during the update.
   * @throws IOException
   * @throws FileNotFoundException
   */
  public void updateCatalogMetadata(Product product, Metadata newMetadata)
      throws CatalogException, FileNotFoundException, IOException {
    System.getProperties().load(
        new FileInputStream(CurationService.config.getFileMgrProps()));
    Catalog catalog = GenericFileManagerObjectFactory
        .getCatalogServiceFromFactory("org.apache.oodt.cas.curation.util.CuratorLuceneCatalogFactory");
    
    Metadata oldMetadata = catalog.getMetadata(product);
    List<Reference> references = catalog.getProductReferences(product);
    Product newProduct = new Product(product.getProductName(), product
        .getProductType(), product.getProductStructure(), product
        .getTransferStatus(), product.getProductReferences());
    // Constructor is bugged and doesn't set transfer status
    newProduct.setTransferStatus(product.getTransferStatus());
    catalog.removeMetadata(oldMetadata, product);
    catalog.removeProduct(product);
    newProduct.setProductId(product.getProductId());
    catalog.addProduct(newProduct);
    newProduct.setProductReferences(references);
    catalog.addProductReferences(newProduct);
    catalog.addMetadata(newMetadata, newProduct);
  }


  private Metadata getProductTypeMetadataForPolicy(String policy,
      String productTypeName) throws MalformedURLException,
      InstantiationException, RepositoryManagerException {
    String rootPolicyPath = this.cleanse(CurationService.config
        .getPolicyUploadPath());
    String policyPath = new File(rootPolicyPath + policy).toURL()
        .toExternalForm();
    String[] policies = { policyPath };
    XMLRepositoryManager repMgr = new XMLRepositoryManager(Arrays
        .asList(policies));
    ProductType productType = repMgr.getProductTypeByName(productTypeName);
    
    return productType.getTypeMetadata();
  }
  
  private Metadata writeProductTypeMetadata(String policy,
      String productTypeName, Metadata metadata) throws Exception {
    String rootPolicyPath = this.cleanse(CurationService.config
        .getPolicyUploadPath());
    String policyPath = new File(rootPolicyPath + policy).toURL()
        .toExternalForm();
    String[] policies = { policyPath };
    XMLRepositoryManager repMgr = new XMLRepositoryManager(Arrays
        .asList(policies));

    ProductType productType = repMgr.getProductTypeByName(productTypeName);
    productType.setTypeMetadata(metadata);
    
    CurationXmlStructFactory.writeProductTypeXmlDocument(repMgr
        .getProductTypes(), rootPolicyPath + policy + "/product-types.xml");

    // refresh the config on the fm end
    CurationService.config.getFileManagerClient().refreshConfigAndPolicy();
    
    return productType.getTypeMetadata();
  }
  
  private String cleanse(String origPath) {
    String retStr = origPath;
    if (!retStr.endsWith("/")) {
      retStr += "/";
    }
    return retStr;
  }
}
