/*
 * Licensed Materials - Property of Perforce Software, Inc. 
 * © Copyright Perforce Software, Inc. 2014, 2021 
 * © Copyright IBM Corp. 2009, 2014
 * © Copyright ILOG 1996, 2009
 * All Rights Reserved.
 *
 * Note to U.S. Government Users Restricted Rights:
 * The Software and Documentation were developed at private expense and
 * are "Commercial Items" as that term is defined at 48 CFR 2.101,
 * consisting of "Commercial Computer Software" and
 * "Commercial Computer Software Documentation", as such terms are
 * used in 48 CFR 12.212 or 48 CFR 227.7202-1 through 227.7202-4,
 * as applicable.
 */
package ilog.views.maps.format.fme;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;

import ilog.views.io.IlvInputStream;
import ilog.views.io.IlvOutputStream;
import ilog.views.io.IlvReadFileException;
import ilog.views.maps.IlvMapGeometry;
import ilog.views.maps.IlvMapReusableFeatureIterator;
import ilog.views.maps.beans.IlvExceptionMessage;
import ilog.views.maps.format.IlvDefaultFeatureFilter;
import ilog.views.maps.format.IlvDefaultTilableDataSource;
import ilog.views.maps.format.IlvFeatureClassInformation;
import ilog.views.maps.format.IlvGeometryClassFilter;
import ilog.views.maps.tiling.IlvMapRegionOfInterestIterator;

/**
 * A data source to read data through the FME bridge.
 */
public class IlvFMEDataSource extends IlvDefaultTilableDataSource {
  static final String FORMAT = "format"; //$NON-NLS-1$
  private String format;

  /**
   * Creates a new <code>IlvFMEDataSource</code>.
   * 
   * @param stream
   *          The stream to read from.
   * @throws IlvReadFileException
   */
  public IlvFMEDataSource(IlvInputStream stream) throws IlvReadFileException {
    super(stream);
    setFormat(stream.readString(FORMAT));
  }

  /**
   * Constructs an <code>IlvS57DataSource</code> from the specified file name.
   * 
   * @param filename
   *          The name of the S57 file to read.
   * @param format
   *          The name of the FME format.
   * @throws MalformedURLException
   *           if the path cannot be parsed as a URL
   */
  public IlvFMEDataSource(String filename, String format) throws MalformedURLException {
    super(filename);
    setFormat(format);
  }

  /**
   * Constructs an <code>IlvS57DataSource</code> from the specified URL.
   * 
   * @param url
   *          The name of the S57 file to read.
   * @param format
   *          The name of the FME format.
   * @throws IOException
   */
  public IlvFMEDataSource(URL url, String format) throws IOException {
    super(url);
    setFormat(format);
  }

  private void setFormat(String format) {
    this.format = format;
    if (featureIterator != null) {
      ((IlvFMEReader) featureIterator).setFormat(format);
    }
  }

  private boolean featuresInited;

  Override
  protected void initFeatureList() {
    try {
      if (featuresInited) {
        return;
      }
      featuresInited = true;
      nameMap.clear();
      if (featureIterator != null) {
        IlvFMEReader r = (IlvFMEReader) featureIterator;
        String[] layers;
        layers = r.readLayerList();
        if (layers != null) {
          for (int i = 0; i < layers.length; i++) {
            nameMap.put(layers[i], layers[i]);
          }
        }
      }
    } catch (Throwable e) {
      new IlvExceptionMessage(e, null);
    }
  }

  Override
  protected IlvMapReusableFeatureIterator createFeatureIterator(String fileName) {
    return new IlvFMEReader(fileName);
  }

  Override
  protected IlvMapReusableFeatureIterator createFeatureIterator(URL url) {
    return new IlvFMEReader(url);
  }

  Override
  protected IlvDefaultFeatureFilter createDefaultFilter() {
    return new IlvDefaultFeatureFilter(IlvFMEReader.FME_FEATURE_TYPE, this);
  }

  /**
   * Creates an iterator that iterates through the map features, for a specific
   * area of interest.
   * 
   * @param featureValue
   *          A feature value to filter features with.
   * @param geometryClass
   *          A subclass of {@link IlvMapGeometry} to prevent the mixing of
   *          different types of features on the same layer.
   * @return The feature iterator.
   */
  Override
  protected IlvMapRegionOfInterestIterator createTiledIterator(IlvFeatureClassInformation featureValue,
      IlvGeometryClassFilter geometryClass) {
    IlvFMEReader initial = (IlvFMEReader) getFeatureIterator();
    return initial.deriveReader(featureValue, geometryClass);
  }

  /**
   * @see ilog.views.maps.datasource.IlvMapDataSource#write(ilog.views.io.IlvOutputStream)
   */
  Override
  public void write(IlvOutputStream stream) throws IOException {
    super.write(stream);
    stream.write(FORMAT, format);
  }

  /**
   * @return The layer list.
   */
  SuppressWarnings("rawtypes")
  public HashMap getNameMap() {
    initFeatureList();
    return nameMap;
  }
}