/*
 * 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.net.URL;
import java.util.Enumeration;

import javax.swing.SwingUtilities;

import ilog.views.IlvManagerLayer;
import ilog.views.maps.IlvMapLayerTreeProperty;
import ilog.views.maps.IlvMapUtil;
import ilog.views.maps.beans.IlvExceptionMessage;
import ilog.views.maps.beans.IlvMapLayer;
import ilog.views.maps.beans.IlvMapLayerTreeModel;
import ilog.views.maps.datasource.IlvMapDataSource;
import ilog.views.maps.datasource.IlvMapDataSourceModel;
import ilog.views.maps.datasource.IlvMapDataSourceProperty;
import ilog.views.maps.graphic.style.IlvMapCompositeStyle;
import ilog.views.maps.graphic.style.IlvMapStyle;
import ilog.views.maps.theme.IlvMapDynamicStyle;
import ilog.views.maps.theme.IlvMapStyleController;
import ilog.views.maps.theme.IlvMapStyleControllerProperty;
import ilog.views.tiling.IlvTiledLayer;

/**
 * Thread loading files in background.
 */
public class LoadDataRunnable extends Thread {
  private final String[] fileNames;
  private final URL[] url;
  IlvMapLayerTreeModel ltm;
  IlvMapDataSourceModel model;
  private boolean interrupted = false;
  private final ImportAction importer;

  /**
   * 
   * @param importer
   * @param fileNames
   */
  public LoadDataRunnable(ImportAction importer, String[] fileNames) {
    super();
    if (importer instanceof LoadAnythingAction) {
      LoadAnythingAction ls = (LoadAnythingAction) importer;
      this.importer = ls.getSelectedAction();
    } else {
      this.importer = importer;
    }
    if (importer.getStopButton() != null) {
      importer.getStopButton().addThread(this);
    }
    ltm = IlvMapLayerTreeProperty.GetMapLayerTreeModel(importer.getView().getManager());
    model = IlvMapDataSourceProperty.GetMapDataSourceModel(importer.getView().getManager());
    setName("LoadInBackround"); //$NON-NLS-1$
    setPriority(Thread.MIN_PRIORITY);
    this.fileNames = fileNames;
    this.url = null;
  }

  /**
   * Creates a loading thread for the import action.
   * 
   * @param importer
   * @param url
   */
  public LoadDataRunnable(ImportAction importer, URL[] url) {
    super();
    fileNames = null;
    this.url = url;
    if (importer instanceof LoadAnythingAction) {
      LoadAnythingAction ls = (LoadAnythingAction) importer;
      this.importer = ls.getSelectedAction();
    } else {
      this.importer = importer;
    }
    if (importer.getStopButton() != null) {
      importer.getStopButton().addThread(this);
    }
    ltm = IlvMapLayerTreeProperty.GetMapLayerTreeModel(importer.getView().getManager());
    model = IlvMapDataSourceProperty.GetMapDataSourceModel(importer.getView().getManager());
    setName("LoadInBackround"); //$NON-NLS-1$
    setPriority(Thread.MIN_PRIORITY);
  }

  void stopCleanly() {
    interrupted = true;
    interrupt();
  }

  void insertDataSource(IlvMapLayer parent, IlvMapDataSource d) {
    if (d == null) {
      return;
    }
    IlvMapLayer layer = d.getInsertionLayer();
    layer.setName(d.getName());
    IlvMapStyleController themeControl = IlvMapStyleControllerProperty
        .GetMapStyleController(importer.getView().getManager());
    IlvMapStyle childStyle = layer.getStyle();
    if (parent != null) {
      IlvMapDynamicStyle[] t = themeControl.getThemes(layer);
      for (int i = 0; i < t.length; i++) {
        t[i].getStyle().setParent(parent.getStyle());
      }
      if (childStyle != null) {
        childStyle.setParent(parent.getStyle());
      }
    }
    if (layer.getParent() == null) {
      ltm.addChild(parent, layer);
    }
    model.insert(d);
  }

  void refreshTiles() {
    int nl = importer.getView().getManager().getLayersCount();
    for (int i = 0; i < nl; i++) {
      IlvManagerLayer l = importer.getView().getManager().getManagerLayer(i);
      if (l instanceof IlvTiledLayer) {
        ((IlvTiledLayer) l).getTileController().updateView(importer.getView());
      }
    }

  }

  /**
   * Main thread running method. Will go through all datasources returned by
   * {@link ImportAction#getDataSources(String[])} and add them, and their
   * layers, to the different tree models.
   */
  Override
  public void run() {
    try {
      IlvMapStyleController themeController = IlvMapStyleControllerProperty
          .GetMapStyleController(importer.getView().getManager());
      IlvMapLayer parent = ltm.findChildLayer(null, importer.getFormatName());
      if (parent == null) {
        parent = new IlvMapLayer();
        parent.setName(importer.getFormatName());
        IlvMapCompositeStyle parentStyle = new IlvMapCompositeStyle();
        // parentStyle.addStyle(new IlvRasterStyle());
        parent.setStyle(parentStyle);
        ltm.addChild(null, parent);
      }
      if (interrupted) {
        end();
        return;
      }
      Enumeration<?> e = null;
      if (fileNames != null)
        e = importer.getDataSources(fileNames);
      else if (url != null)
        e = importer.getDataSources(url);
      Object o = fileNames;
      if (o == null)
        o = url;
      importer.setAdvancement(ImportAction.LOADING, o, 100);
      importer.setAdvancement(ImportAction.RENDERING, o, 1);
      if (e == null) {
        end();
        return;
      }
      while (e.hasMoreElements()) {
        if (interrupted) {
          end();
          return;
        }
        IlvMapDataSource d = (IlvMapDataSource) e.nextElement();
        if (d != null && !interrupted) {
          insertDataSource(parent, d);
          themeController.updateTheme(importer.getView(), d.getInsertionLayer());
          d.start();
        } else {
          end();
          return;
        }
        if (interrupted) {
          end();
          return;
        }
      }
    } catch (Throwable th) {
      new IlvExceptionMessage(th, IlvMapUtil.getString(ImportAction.class, "ImportAction.Error")); //$NON-NLS-1$
    }
    end();
  }

  /**
   * Called after the run, wether of not it has been interrupted, to refresh the
   * tiles and the views.
   */
  public void end() {
    SwingUtilities.invokeLater(new Runnable() {
      Override
      public void run() {
        ltm.arrangeLayers();
        IlvMapStyleController themeController = IlvMapStyleControllerProperty
            .GetMapStyleController(importer.getView().getManager());
        themeController.updateCurrentTheme();
        refreshTiles();
        importer.getView().getManager().reDraw();
        Object o = fileNames;
        if (o == null)
          o = url;
        importer.setAdvancement(ImportAction.RENDERING, o, 100);
        if (importer.getStopButton() != null) {
          importer.getStopButton().removeThread(LoadDataRunnable.this);
        }
      }
    });
  }

  /**
   * @return Returns the interrupted.
   */
  public boolean wasStoppedCleanly() {
    return interrupted;
  }
}