/*
 * 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 plugins;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Enumeration;

import javax.swing.JComponent;

import ilog.views.IlvManagerView;
import ilog.views.maps.beans.IlvExceptionMessage;
import ilog.views.maps.datasource.IlvDefaultMapDataSource;
import ilog.views.maps.datasource.IlvMapDataSource;
import ilog.views.maps.raster.IlvRasterAbstractReader;
import ilog.views.maps.raster.datasource.IlvRasterDataSourceFactory;
import ilog.views.maps.raster.datasource.IlvThreadMonitoringData;

/**
 * Default image load action.
 */
public abstract class DefaultLoadAction extends ImportAction {
  private boolean splitting = true;
  private boolean threading = true;

  static class FileTableLoader implements Enumeration<IlvMapDataSource> {
    final Object fileNames[];
    int currentFile;
    double basePct;
    final DefaultLoadAction importAction;

    FileTableLoader(Object fileNames[], DefaultLoadAction importAction) {
      this.fileNames = fileNames;
      currentFile = 0;
      basePct = 100.0 / fileNames.length;
      this.importAction = importAction;
    }

    /**
     * @see java.util.Enumeration#hasMoreElements()
     */
    Override
    public boolean hasMoreElements() {
      boolean hasMore = currentFile < fileNames.length;
      return hasMore;
    }

    /**
     * @see java.util.Enumeration#nextElement()
     */
    Override
    public IlvMapDataSource nextElement() {
      if (hasMoreElements()) {
        int i = currentFile;
        currentFile++;
        File f = new File(fileNames[i].toString());
        IlvThreadMonitoringData monitorData = new IlvThreadMonitoringData(importAction.getMonitor(), fileNames,
            f.getName() + " " + importAction.getActivityDescription(RENDERING), //$NON-NLS-1$
            (int) (basePct * i), (int) (basePct * (i + 1)));
        IlvMapDataSource dataSource;
        try {
          IlvRasterAbstractReader r;
          if (fileNames[i] instanceof URL) {
            r = importAction.makeReader((URL) fileNames[i]);
          } else {
            r = importAction.makeReader(fileNames[i].toString());
          }
          if (r != null) {
            dataSource = IlvRasterDataSourceFactory.buildTiledImageDataSource(importAction.getView().getManager(), r,
                importAction.isSplitting(), importAction.isThreading(), monitorData);
          } else {
            dataSource = new IlvDefaultMapDataSource();
          }
        } catch (IOException e) {
          new IlvExceptionMessage(e, null);
          dataSource = new IlvDefaultMapDataSource();
        }
        dataSource.setName(importAction.getFormatName() + " " + f.getName()); //$NON-NLS-1$
        return dataSource;
      }
      return null;
    }

  }

  /**
   * Creates an action for the specified view
   * 
   * @param view
   *          view to add map data to.
   */
  public DefaultLoadAction(IlvManagerView view) {
    super(view);
  }

  /**
   * Creates an image reader for the file specified.
   * 
   * @param fileName
   *          file to read.
   * @return a raster reader able to generate images.
   * @throws IOException
   */
  public abstract IlvRasterAbstractReader makeReader(String fileName) throws IOException;

  /**
   * Creates an image reader for the URL specified.
   * 
   * @param url
   *          url to read.
   * @return a raster reader able to generate images.
   * @throws IOException
   */
  public abstract IlvRasterAbstractReader makeReader(URL url) throws IOException;

  /**
   * Loads data by creating a data source with a specific reader for each of the
   * files passed.
   * 
   * @see #makeReader(String)
   * @see plugins.ImportAction#getDataSources(java.lang.String[])
   */
  Override
  public Enumeration<IlvMapDataSource> getDataSources(String fileNames[]) {
    return new FileTableLoader(fileNames, this);
  }

  /**
   * Loads data by creating a data source with a specific reader for each of the
   * files passed.
   * 
   * @see #makeReader(String)
   * @see plugins.ImportAction#getDataSources(java.lang.String[])
   */
  Override
  public Enumeration<IlvMapDataSource> getDataSources(URL urls[]) {
    return new FileTableLoader(urls, this);
  }

  /**
   * Returns null by default, but can be overridden in subclasses.
   * 
   * @see plugins.ImportAction#getAccessory()
   */
  Override
  public JComponent getAccessory() {
    return null;
  }

  /**
   * @see plugins.ImportAction#getFormatName()
   */
  Override
  public abstract String getFormatName();

  /**
   * Returns whether this action will create a data source that splits images.
   * 
   * @return Returns whether this action will create a data source that splits
   *         images.
   */
  public boolean isSplitting() {
    return splitting;
  }

  /**
   * Indicates whether this action will create a data source that splits images.
   * Default is true.
   * 
   * @param splitting
   *          Indicates whether this action will create a data source that
   *          splits images.
   */
  public void setSplitting(boolean splitting) {
    this.splitting = splitting;
  }

  /**
   * Returns whether this action will create a data source that threads image
   * loading.
   * 
   * @return Returns whether this action will create a data source that threads
   *         image loading.
   */
  public boolean isThreading() {
    return threading;
  }

  /**
   * Indicates whether this action will create a data source that threads image
   * loading. Default is true.
   * 
   * @param threading
   *          Indicates whether this action will create a data source that
   *          threads image loading.
   */
  public void setThreading(boolean threading) {
    this.threading = threading;
  }
}