/*
 * 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.product.handlers.ofsn;

//JDK imports
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

//APACHE imports
import org.apache.tika.mime.MediaType;
import org.apache.tika.mime.MimeTypesFactory;

//OODT imports
import org.apache.oodt.commons.xml.XMLUtils;
import org.apache.oodt.product.handlers.ofsn.metadata.OFSNMetKeys;
import org.apache.oodt.product.handlers.ofsn.metadata.OFSNXMLConfigMetKeys;
import org.apache.oodt.product.handlers.ofsn.metadata.OFSNXMLMetKeys;
import org.apache.oodt.product.handlers.ofsn.metadata.XMLQueryMetKeys;
import org.apache.oodt.product.handlers.ofsn.util.OFSNObjectFactory;
import org.apache.oodt.product.handlers.ofsn.util.OFSNUtils;
import org.apache.oodt.product.LargeProductQueryHandler;
import org.apache.oodt.product.ProductException;
import org.apache.oodt.xmlquery.LargeResult;
import org.apache.oodt.xmlquery.Result;
import org.apache.oodt.xmlquery.XMLQuery;

/**
 * 
 * An extensible implementation of the PDS-inspired Online File Specification
 * Name (OFSN) style product server. See the ofsn-ps.xml file for a detailed
 * specification of the configuration and motivation behind this product
 * handler.
 * 
 * @author mattmann
 * @version $Revision$
 */
public class OFSNFileHandler implements LargeProductQueryHandler,
    XMLQueryMetKeys, OFSNXMLMetKeys, OFSNMetKeys, OFSNXMLConfigMetKeys {

  private static final Logger LOG = Logger.getLogger(OFSNFileHandler.class
      .getName());

  private static final String CMD_SEPARATOR = ";";

  // by default return dir size on listing commands
  private boolean computeDirSize = true;
  
  // by default return file size on listing commands
  private boolean computeFileSize = true;

  private OFSNFileHandlerConfiguration conf;

  private static Map<String, Object> HANDLER_CACHE;

  public OFSNFileHandler() throws InstantiationException {
    // init conf here
    String xmlConfigFilePath = System.getProperty(OFSN_XML_CONF_FILE_KEY);
    this.computeDirSize = Boolean.getBoolean(OFSN_COMPUTE_DIR_SIZE);
    this.computeFileSize = Boolean.getBoolean(OFSN_COMPUTE_FILE_SIZE);


    if (xmlConfigFilePath == null) {
      throw new InstantiationException(
          "Must define xml configuration file path via property : ["
              + OFSN_XML_CONF_FILE_KEY + "]");
    }

    try {
      this.conf = OFSNFileHandlerConfigurationReader
          .getConfig(xmlConfigFilePath);
    } catch (FileNotFoundException e) {
      throw new InstantiationException("xml configuration file: ["
          + xmlConfigFilePath + "] not found!");
    }

    if (this.conf.getProductRoot() == null) {
      throw new InstantiationException(
          "Must define: [productRoot] attribute in XML configuration!");
    }

    // used to cache handlers -- map of RT type to Get/List handler instance
    HANDLER_CACHE = new HashMap<String, Object>();
  }

  /*
   * (non-Javadoc)
   * 
   * @see org.apache.oodt.product.QueryHandler#query(org.apache.oodt.xmlquery.XMLQuery)
   */
  public XMLQuery query(XMLQuery xmlQuery) throws ProductException {
    String ofsn = OFSNUtils.extractFieldFromQuery(xmlQuery, OFSN);
    String cmd = OFSNUtils.extractFieldFromQuery(xmlQuery, RETURN_TYPE);
    validate(ofsn, cmd);
    String cmdId = ofsn + CMD_SEPARATOR + cmd;
    OFSNHandlerConfig cfg = this.conf.getHandlerConfig(cmd);
    validateHandlerConfig(cfg, cmd);

    String realPath = this.conf.getProductRoot() + ofsn;

    if (isListingCmd(cmd)) {
      ByteArrayOutputStream outStream = new ByteArrayOutputStream();
      OFSNListHandler handler = getListHandler(cmd, cfg.getClassName());
      File[] fileList = handler.getListing(realPath);
      generateOFSNXml(fileList, cfg, outStream);
      xmlQuery.getResults().add(
          new Result(cmdId, XML_MIME_TYPE, null, cmdId, Collections.EMPTY_LIST,
              outStream.toString()));
    } else if (isGetCmd(cmd)) {
      OFSNGetHandler handler = getGetHandler(cmd, cfg.getClassName());
      String rtAndPath = cmd + CMD_SEPARATOR + realPath;
      String mimeType;
      
      // check for and use mimetype conf property if available
      if (cfg.getHandlerConf().containsKey(PROPERTY_MIMETYPE_ATTR)) {
    	  MediaType mediaType = MediaType.parse(cfg.getHandlerConf()
    			  .getProperty(PROPERTY_MIMETYPE_ATTR));
    	  if (mediaType == null) {
    		  LOG.log(Level.WARNING, "MIME type ["
    				  +cfg.getHandlerConf().getProperty(PROPERTY_MIMETYPE_ATTR)+"] specified "
    				  +"for handler ["+cfg.getClassName()+"] invalid. Defaulting to MIME type ["
    				  +MediaType.OCTET_STREAM.toString()+"]");
    		  mediaType = MediaType.OCTET_STREAM;
    	  }
    	  mimeType = mediaType.toString();
      } else { // use default mimetype of product on disk
          try {
              mimeType = MimeTypesFactory.create().getMimeType(new File(realPath)).getName();
          } catch (Exception e) {
              mimeType = null;
          }
      }
      
      xmlQuery.getResults().add(
          new LargeResult(/* id */rtAndPath,/* mimeType */ mimeType, /* profileID */null, 
        		  /* resourceID */new File(realPath).getName(), Collections.EMPTY_LIST, 
        		  handler.sizeOf(realPath)));
    } else {
      throw new ProductException("return type: [" + cmd + "] is unsupported!");
    }

    return xmlQuery;

  }

  /*
   * (non-Javadoc)
   * 
   * @see org.apache.oodt.product.LargeProductQueryHandler#close(java.lang.String)
   */
  public void close(String id) throws ProductException {
    // nothing to do
  }

  /*
   * (non-Javadoc)
   * 
   * @see
   * org.apache.oodt.product.LargeProductQueryHandler#retrieveChunk(java.lang.String,
   * long, int)
   */
  public byte[] retrieveChunk(String id, long offset, int length)
      throws ProductException {
    // unmarshall the return type and path
    String[] rtTypeAndPathArr = id.split(CMD_SEPARATOR);
    String rtType = rtTypeAndPathArr[0];
    String filepath = rtTypeAndPathArr[1];

    OFSNGetHandler handler = getGetHandler(rtType, this.conf
        .getHandlerClass(rtType));
    
    return handler.retrieveChunk(filepath, offset, length);
  }

  private void generateOFSNXml(File[] mlsFileList, OFSNHandlerConfig cfg,
      OutputStream outStream) {
    XMLUtils.writeXmlToStream(OFSNUtils.getOFSNDoc(Arrays.asList(mlsFileList),
        cfg, this.conf.getProductRoot(), this.computeDirSize, this.computeFileSize),
        outStream);
  }

  private void validate(String ofsn, String cmd) throws ProductException {
    if (ofsn == null || cmd == null || (ofsn != null && ofsn.equals(""))
        || (cmd != null && cmd.equals(""))) {
      throw new ProductException("must specify OFSN and RT parameters!");
    } else if (!OFSNUtils.validateOFSN(ofsn)) {
      throw new ProductException("OFSN is invalid");
    }
  }

  private void validateHandlerConfig(OFSNHandlerConfig cfg, String cmd)
      throws ProductException {
    if (cfg == null) {
      throw new ProductException("Unrecognized command: [" + cmd + "]!");
    }
  }

  private OFSNListHandler getListHandler(String rtType, String className) {
    if (HANDLER_CACHE.containsKey(rtType)) {
      return (OFSNListHandler) HANDLER_CACHE.get(rtType);
    } else {
      OFSNListHandler handler = OFSNObjectFactory.getListHandler(className);
      LOG.log(Level.INFO, "Getting handler config for RT: ["+rtType+"]");
      handler.configure(this.conf.getHandlerConfig(rtType).getHandlerConf());
      HANDLER_CACHE.put(rtType, handler);
      return handler;
    }
  }

  private OFSNGetHandler getGetHandler(String rtType, String className) {
    if (HANDLER_CACHE.containsKey(rtType)) {
      return (OFSNGetHandler) HANDLER_CACHE.get(rtType);
    } else {
      OFSNGetHandler handler = OFSNObjectFactory.getGetHandler(className);
      handler.configure(this.conf.getHandlerConfig(rtType).getHandlerConf());
      HANDLER_CACHE.put(rtType, handler);
      return handler;
    }
  }

  private boolean isListingCmd(String cmd) throws ProductException {
    OFSNHandlerConfig cfg = this.conf.getHandlerConfig(cmd);
    if (cfg == null) {
      throw new ProductException("Unrecognized command: [" + cmd + "]!");
    }

    if (cfg.getType().equals(LISTING_CMD)) {
      return true;
    } else
      return false;
  }

  private boolean isGetCmd(String cmd) throws ProductException {
    OFSNHandlerConfig cfg = this.conf.getHandlerConfig(cmd);

    if (cfg.getType().equals(GET_CMD)) {
      return true;
    } else
      return false;
  }

}
