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

import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.security.AccessControlException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;

import ilog.views.IlvManagerView;
import ilog.views.maps.IlvMapOutputStream;
import ilog.views.maps.IlvMapUtil;
import ilog.views.util.IlvImageUtil;
import ilog.views.util.waitcursor.IlvWaitCursorManager;
import plugins.ImportAction;
import plugins.ImportManager;
import plugins.LoadAnythingAction;
import plugins.StopButton;
import utils.IvlFileManager;

/**
 * Adds the import buttons to the base demo.
 */
SuppressWarnings("serial")
public class MapBuilder extends BaseDemo {
  static JFrame frame;
  static {
    // set up the default map directory
    String local = IlvMapUtil.getString(MapBuilder.class, "MapBuilder.LocalDirectory"); //$NON-NLS-1$
    boolean exists;
    try {
      exists = new File(local).exists();
    } catch (AccessControlException e) {
      exists = false;
    }
    if (exists)
      ImportManager.setBaseMapDirectory(local);
    else
      ImportManager.setBaseMapDirectory(IlvMapUtil.getString(MapBuilder.class, "MapBuilder.DistantDirectory")); //$NON-NLS-1$
    // make sure we use japanese fonts if they exist
    if (Locale.getDefault().getLanguage() == "ja") { //$NON-NLS-1$
      try {
        Method m = GraphicsEnvironment.class.getMethod("preferLocaleFonts", (Class[]) null); //$NON-NLS-1$
        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
        m.invoke(ge, (Object[]) null);
      } catch (Exception e) {
        // too bad
      }
    }
  }

  List<ImportAction> allInstances = new ArrayList<ImportAction>();

  // Class that starts import plug-in actions through reflection.
  static class ImportActionFactory {
    final String className;

    ImportActionFactory(final String className) {
      this.className = className;
    }

    /**
     * @return Returns the className.
     */
    public String getClassName() {
      return className;
    }

    ImportAction getInstance(IlvManagerView view) {
      ImportAction action = null;
      try {
        Class<?> pluginClass = Class.forName(getClassName());
        Constructor<?> c = pluginClass.getConstructor(new Class[] { IlvManagerView.class });
        action = (ImportAction) c.newInstance(new Object[] { view });
      } catch (Exception e1) {
        e1.printStackTrace();
      }
      return action;
    }
  }

  /**
   * Returns a table containing all the Import actions created.
   * 
   * @return Returns a table containing all the Import actions created.
   */
  public ImportAction[] getAllImportActions() {
    return (ImportAction[]) allInstances.toArray(new ImportAction[0]);
  }

  /**
   * Button or menu to import data.
   */
  protected JComponent importBtn;
  private LoadAnythingAction dropAction;

  /**
   * Returns a list of class names to be used as import actions in the import
   * menu.
   * 
   * @return the list of class names to be used as import actions in the import
   *         menu.
   */
  protected List<String> getImportActionClassNames() {
    List<String> list = new ArrayList<String>();
    list.add("plugins.LoadAnythingAction"); //$NON-NLS-1$
    list.add("plugins.ShapeLoadAction");//$NON-NLS-1$
    list.add("plugins.TigerLoadAction");//$NON-NLS-1$
    list.add("plugins.MIDMIFLoadAction");//$NON-NLS-1$
    list.add("plugins.VMAPLoadAction");//$NON-NLS-1$
    list.add("plugins.GTopo30LoadAction");//$NON-NLS-1$
    list.add("plugins.GeotiffLoadAction");//$NON-NLS-1$
    list.add("plugins.USRPLoadAction");//$NON-NLS-1$
    list.add("plugins.ASRPLoadAction");//$NON-NLS-1$
    list.add("plugins.CADRGLoadAction");//$NON-NLS-1$
    list.add("plugins.BasicImageLoadAction");//$NON-NLS-1$
    list.add("plugins.DTEDAvgLoadAction"); //$NON-NLS-1$
    list.add("plugins.DTEDMinLoadAction"); //$NON-NLS-1$
    list.add("plugins.DTEDMaxLoadAction"); //$NON-NLS-1$
    list.add("plugins.DTEDLoadAction"); //$NON-NLS-1$
    list.add("plugins.DXFLoadAction");//$NON-NLS-1$
    list.add("plugins.KMLLoadAction");//$NON-NLS-1$
    list.add("plugins.S57LoadAction");//$NON-NLS-1$
    list.add("plugins.S57LoadCatalogAction");//$NON-NLS-1$
    list.add("plugins.DAFIFLoadAction");//$NON-NLS-1$
    list.add("plugins.IBMDB2LoadAction"); //$NON-NLS-1$
    list.add("plugins.IBMInformixLoadAction"); //$NON-NLS-1$
    list.add("plugins.SDOLoadAction"); //$NON-NLS-1$
    list.add("plugins.WMSLoadAction"); //$NON-NLS-1$
    list.add("plugins.SVGLoadAction");//$NON-NLS-1$
    return list;
  }

  /**
   * launch the map builder.
   */
  public MapBuilder() {
    super();
    // Make sure the swing construction is called in Swing event thread.
    ilog.views.util.swing.IlvSwingUtil.invokeAndWait(new Runnable() {
      Override
      public void run() {
        StopButton stop = new StopButton();
        Image image;
        try {
          image = IlvImageUtil.getImageFromFile(MapBuilder.class, "/icons/stop_icon.gif");//$NON-NLS-1$
          stop.setToolTipText(IlvMapUtil.getString(MapBuilder.class, "MapBuilder.StopTip")); //$NON-NLS-1$
          stop.setIcon(new ImageIcon(image));
          stop.setMargin(new Insets(2, 2, 2, 2));
        } catch (IOException e1) {
          stop.setText("X"); //$NON-NLS-1$
        }
        stop.setSize(stop.getPreferredSize());
        view.add(stop);
        List<String> actionNames = getImportActionClassNames();

        // Exporter
        final ImportManager manager = new ImportManager();
        for (int ip = 0; ip < actionNames.size(); ip++) {
          ImportActionFactory plugin = new ImportActionFactory(actionNames.get(ip).toString());
          final ImportAction i = plugin.getInstance(view);
          if (!i.isAvailable())
            continue;
          allInstances.add(i);
          i.setPreferences(getPreferences());
          i.setStopButton(stop);
          manager.addChoosableFileFilter(i);
          manager.setIgnoreFilterChange(true);
        }
        manager.setIgnoreFilterChange(false);
        JMenuItem b = new MBMenuItem("MapBuilder.Import", true); //$NON-NLS-1$
        b.addActionListener(new ActionListener() {
          Override
          public void actionPerformed(ActionEvent e) {
            manager.showOpenDialog(view);
          }
        });
        fileMenu.insert(b, 1);
        importBtn = b;
        
        ImportAction[] list = getAllImportActions();
        for (int i = 0; i < list.length; i++) {
          if (list[i] instanceof LoadAnythingAction) {
            dropAction = (LoadAnythingAction) list[i];
            dropAction.setActions(list);
          }
        }
      }
    });// event thread runnable
  }

  Override
  public void setCurrentFile(String fileName) {
    super.setCurrentFile(fileName);
    updateTitle();
  }

  Override
  public void setModified(boolean modified) {
    super.setModified(modified);
    updateTitle();
  }

  /**
   * Updates the title of the frame with appropriate current file name and
   * modified state.
   */
  protected void updateTitle() {
    String f = ((getCurrentFile() == null) ? "" : " " + getCurrentFile()) //$NON-NLS-1$//$NON-NLS-2$
        + ((isModified()) ? IlvMapUtil.getString(MapBuilder.class, "MapBuilder.ModifiedMap") : ""); //$NON-NLS-1$ //$NON-NLS-2$
    if (frame != null) // Applet 
      frame.setTitle(IlvMapUtil.getString(MapBuilder.class, "MapBuilder.Title") + f); //$NON-NLS-1$
  }

  /**
   * Main method
   * 
   * @param args
   *          (ignored)
   */
  public static void main(String[] args) {
    BaseDemo.showSplashScreen();
    SwingUtilities.invokeLater(new Runnable() {
      Override
      public void run() {
        final MapBuilder app = new MapBuilder();
        frame = new JFrame(IlvMapUtil.getString(MapBuilder.class, "MapBuilder.Title")); //$NON-NLS-1$
        // JViews Bug Report 2005.189
        try {
          frame.setIconImage(IlvImageUtil.getImageFromFile(BaseDemo.class, "/icons/default_frame_icon.gif")); //$NON-NLS-1$
        } catch (IOException e1) {
          // ignore.
        }
        app.getPreviewButton().addActionListener(new ActionListener() {
          Override
          public void actionPerformed(ActionEvent ev) {
            app.getPrintingController().printPreview(frame);
          }
        });
        // Action to open the setup dialog box.
        app.getSetupButton().addActionListener(new ActionListener() {
          Override
          public void actionPerformed(ActionEvent ev) {
            app.getPrintingController().setupDialog(frame, true, true);
          }
        });
        // Action to print the document.
        app.getPrintButton().addActionListener(new ActionListener() {
          Override
          public void actionPerformed(ActionEvent ev) {
            try {
              app.getPrintingController().print(true);
            } catch (Exception e) {
              /* ignore exceptions */
            }
          }
        });
        frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
        frame.addWindowListener(new WindowAdapter() {
          Override
          public void windowClosing(WindowEvent e) {
            app.exitApplication();
          }
        });
        frame.getContentPane().add(app);
        IlvWaitCursorManager.init(); // will push an event queue and fix the
                                     // dual
                                     // screen mode problem for 3D
        frame.pack();
        frame.setVisible(true);
      }
    });
  }

  Override
  public void dropFile(File f) {
    if (f.getName().toLowerCase().endsWith(IlvMapOutputStream.getFileSuffix())) {
      IvlFileManager.LoadIvlActionListener loader = new IvlFileManager.LoadIvlActionListener(this);
      loader.doLoad(f);
    } else if (dropAction != null) {
      dropAction.dropFile(f);
    }
  }

}