/*
 * 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.awt.BorderLayout;
import java.awt.Component;
import java.awt.HeadlessException;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.lang.reflect.Field;

import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.filechooser.FileFilter;
import javax.swing.filechooser.FileSystemView;
import javax.swing.filechooser.FileView;

import ilog.views.maps.IlvMapUtil;
import ilog.views.maps.datasource.ibm.IlvDBAbstractConnectionPanel;
import ilog.views.maps.export.SDOConnectionPanel;
import ilog.views.util.java.Version;

/**
 * A Non-modal JFileChooser configured when the loading action (as a file
 * filter) changes. When the selection is approved, it starts the background
 * loading of the data.
 */
public class ImportManager extends JFileChooser {
  JDialog dialog;

  /**
   * Creates a JFileChooser configured when the loading action (as a file
   * filter) changes.
   */
  public ImportManager() {
    // JViews Bug Report 2005.197
    setCurrentDirectory(new File(defaultDirectory));
    setAcceptAllFileFilterUsed(false);
    addPropertyChangeListener(FILE_FILTER_CHANGED_PROPERTY, new PropertyChangeListener() {
      Override
      public void propertyChange(PropertyChangeEvent evt) {
        ImportAction action = getAction();
        if (action != null) {
          filterChange(action);
        }
      }
    });
    addPropertyChangeListener(JFileChooser.SELECTED_FILE_CHANGED_PROPERTY, new PropertyChangeListener() {
      boolean skipThis;

      Override
      public void propertyChange(PropertyChangeEvent evt) {
        if (skipThis) {
          return;
        }
        ImportAction action = getAction();
        if (action != null) {
          action.selectedFileChanged((File) evt.getNewValue());
          // with the "Load all formats" action, this can change the multi
          // selection.
          // manage this by storing currently selected files, changing the flag
          // and restoring the files.
          if (action.isMultiSelectionEnabled() != isMultiSelectionEnabled()) {
            skipThis = true;
            File[] files;
            if (isMultiSelectionEnabled()) {
              files = getSelectedFiles();
            } else {
              files = new File[] { getSelectedFile() };
              // JV-2742
              if (files[0] == null) {
                files = null;
              }
            }
            setMultiSelectionEnabled(action.isMultiSelectionEnabled());
            setSelectedFiles(files);
            skipThis = false;
          }
        }
      }
    });
    addPropertyChangeListener(JFileChooser.DIRECTORY_CHANGED_PROPERTY, new PropertyChangeListener() {
      Override
      public void propertyChange(PropertyChangeEvent evt) {
        ImportAction action = getAction();
        if (action != null) {
          action.directoryChanged((File) evt.getNewValue());
        }
      }
    });
  }

  File getDirectory(ImportAction action) {
    // JViews Bug Report 2005.197
    File f;
    f = new File(getCurrentDirectory(), action.getSubDirectory());
    if (!f.exists()) {
      f = new File(getCurrentDirectory().getParent(), action.getSubDirectory());
    }
    if (!f.exists()) {
      f = getCurrentDirectory();
    }
    return f;
  }

  ImportAction getAction() {
    FileFilter f = getFileFilter();
    if (f instanceof ImportAction) {
      return (ImportAction) f;
    }
    return null;
  }

  /**
   * @inheritDoc
   */
  Override
  public void setFileFilter(FileFilter filter) {
    if (!ignoreFilterChange) {
      super.setFileFilter(filter);
    }
  }

  void filterChange(ImportAction action) {
    JComponent accessory = action.getAccessory();
    FileSystemView view = action.getFileSystemView();
    Component buttonBar = null;
    if (getLayout() instanceof BorderLayout) {
      // JViews Bug Report 2005.182
      BorderLayout layout = (BorderLayout) getLayout();
      if (Version.isJava9OrLater()) {
          // Since the introduction of modules in Java 9, runtime reflective access to
          // a package's non-public members (such as BorderLayout.NORTH) is discouraged.
          // We can access this component without reflection to avoid an "illegal reflective
          // access operation has occurred" message from method Field.setAccessible.
          buttonBar = layout.getLayoutComponent(BorderLayout.NORTH); // Since Java 1.5
      } else {
              try {
                Field f = layout.getClass().getDeclaredField("north"); //$NON-NLS-1$
                f.setAccessible(true);
                buttonBar = (Component) f.get(layout);
              } catch (Throwable t) {
                // no such method in jdk 1.4
              }
      }
    }
    if (view != null) {
      // hide top button bar
      if (buttonBar != null)
        buttonBar.setVisible(false);
      setFileSystemView(view);
    } else {
      if (buttonBar != null)
        buttonBar.setVisible(true);
      try {
        setCurrentDirectory(getDirectory(action));
      } catch (Throwable t) {
        // ignore
      }
      setFileSystemView(FileSystemView.getFileSystemView());
    }
    setAccessory(accessory);
    if (action instanceof SDOLoadAction) {
      SDOLoadAction sdoAction = (SDOLoadAction) action;
      SDOConnectionPanel panel = sdoAction.getSDOConnectionPanel();
      panel.setFileChooser(this);
    }
    // Added by DWA for DB2 and Informix support
    // DB2 and Informix load actions are subclasses of AbstractDBLoadAction
    if (action instanceof AbstractDBLoadAction) {
      AbstractDBLoadAction dbAction = (AbstractDBLoadAction) action;
      IlvDBAbstractConnectionPanel panel = dbAction.getDBConnectionPanel();
      panel.setFileChooser(this);
    }
    setMultiSelectionEnabled(action.isMultiSelectionEnabled());
    setFileSelectionMode(action.getSelectionMode());
    rescanCurrentDirectory();
    if (dialog != null) {
      dialog.pack();
    }
  }

  /**
   * shows a non modal file selection dialog
   * 
   * @see javax.swing.JFileChooser#showDialog(java.awt.Component,
   *      java.lang.String)
   */
  Override
  public int showDialog(Component parent, String approveButtonText) throws HeadlessException {
    dialog = createDialog(parent);
    // JViews Bug Report 2005.189
    dialog.setTitle(IlvMapUtil.getString(ImportManager.class, "ImportManager.DialogTitle")); //$NON-NLS-1$
    dialog.setModal(false);
    rescanCurrentDirectory();
    dialog.setVisible(true);
    return ERROR_OPTION;
  }

  /**
   * @see javax.swing.JFileChooser#cancelSelection()
   */
  Override
  public void cancelSelection() {
    if (dialog != null) {
      dialog.setVisible(false);
      dialog = null;
    }
    fireActionPerformed(CANCEL_SELECTION);
  }

  /**
   * @see javax.swing.JFileChooser#approveSelection()
   */
  Override
  public void approveSelection() {
    ImportAction action = getAction();
    if (action != null) {
      boolean ok = action.approveSelection(getSelectedFiles());
      if (!ok)
        return;
    }
    if (dialog != null) {
      dialog.setVisible(false);
      dialog = null;
    }
    fireActionPerformed(APPROVE_SELECTION);
    if (action != null) {
      openIt(action);
    }
  }

  void openIt(ImportAction action) {
    File[] files;
    if (action.isMultiSelectionEnabled()) {
      files = getSelectedFiles();
    } else {
      files = new File[] { getSelectedFile() };
    }
    String fileNames[] = new String[files.length];
    for (int i = 0; i < fileNames.length; i++) {
      fileNames[i] = files[i].getPath();
    }
    loadInBackground(action, fileNames);
  }

  private static String defaultDirectory = "."; //$NON-NLS-1$
  private boolean ignoreFilterChange;

  /**
   * Creates and starts loading the data sources in a background thread for the
   * selected files.
   * 
   * @param action
   *          action starting the load.
   * @param fileNames
   *          files selected by the user.
   */
  public static void loadInBackground(ImportAction action, final String fileNames[]) {
    action.getMonitor().registerThreadedActivity(fileNames);
    action.getMonitor().updateActivityProgress(fileNames, 1, ImportAction.LOADING);
    LoadDataRunnable t = new LoadDataRunnable(action, fileNames);
    t.start();
  }

  /**
   * Sets the base (parent) map directory for all formats.
   * 
   * @param directory
   *          parent of all format subdirectories.
   */
  public static void setBaseMapDirectory(String directory) {
    defaultDirectory = directory;
  }

  /**
   * @param b
   */
  public void setIgnoreFilterChange(boolean b) {
    ignoreFilterChange = b;
  }

  /**
   * @inheritDoc
   */
  Override
  public FileView getFileView() {
    ImportAction action = getAction();
    if (action != null) {
      FileView v = action.getFileView();
      if (v != null)
        return v;
    }
    return super.getFileView();
  }

}