/*
 * Licensed Materials - Property of Rogue Wave Software, Inc. 
 * © Copyright Rogue Wave Software, Inc. 2014, 2015 
 * © 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 ilog.views.IlvGraphic;
import ilog.views.IlvManagerView;
import ilog.views.maps.IlvAttributeInfoProperty;
import ilog.views.maps.IlvAttributeProperty;
import ilog.views.maps.IlvFeatureAttributeProperty;
import ilog.views.maps.IlvMapLayerTreeProperty;
import ilog.views.maps.IlvMapUtil;
import ilog.views.maps.beans.IlvFeatureSelectorPanel;
import ilog.views.maps.beans.IlvMapLayer;
import ilog.views.maps.beans.IlvMapLayerTreeModel;
import ilog.views.maps.datasource.DataSourceEvent;
import ilog.views.maps.datasource.DataSourceListener;
import ilog.views.maps.datasource.IlvMapDataSource;
import ilog.views.maps.format.IlvDefaultTilableDataSource;
import ilog.views.maps.raster.datasource.IlvThreadMonitoringData;
import ilog.views.maps.theme.IlvMapStyleController;
import ilog.views.maps.theme.IlvMapStyleControllerProperty;

import java.awt.BorderLayout;
import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Vector;

import javax.swing.BorderFactory;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import nodefense.S57DefLess;


/**
 * Class that manages S57 import action.
 * @since JViews 8.0
 */
public class S57LoadAction extends ImportAction {
    //   JV-4113
  /* deal with the scale minimum data */
  private static final class ScaleMimimumManager implements DataSourceListener {
        public void dataSourceLoaded(DataSourceEvent event) {
            IlvMapDataSource ds = event.getDataSource();
            // The main S57 layer
            IlvMapLayer ml = ds.getInsertionLayer();
            IlvMapLayerTreeModel model = IlvMapLayerTreeProperty.GetMapLayerTreeModel(ml.getManager());
            // The layer style controller
            IlvMapStyleController themeControl = IlvMapStyleControllerProperty.GetMapStyleController(ml.getManager());
            // Get all the layers created
            IlvMapLayer layers[] = model.getChildren(ml);
            String invisible=IlvMapUtil.getString(S57LoadAction.class, "S57LoadAction.InvisibleStyleName"); //$NON-NLS-1$
            String visible=IlvMapUtil.getString(S57LoadAction.class, "S57LoadAction.VisibleStyleName"); //$NON-NLS-1$
            for (int il = 0; il < layers.length; il++) {
                IlvAttributeInfoProperty p = layers[il].getStyle().getAttributeInfo();
                String scaleMinAttributeName="Scale minimum"; //$NON-NLS-1$
                String scaleMaxAttributeName="Scale maximum"; //$NON-NLS-1$
                    if (hasAttribute(p,scaleMinAttributeName) || hasAttribute(p,scaleMaxAttributeName)) {
                    // yes - get the first graphic in the layer
                    if (layers[il].getManagerLayer() != null && layers[il].getManagerLayer().getCardinal() > 0) {
                        IlvGraphic g = layers[il].getManagerLayer().getObject(0);
                        // get its attributes
                        IlvFeatureAttributeProperty att = (IlvFeatureAttributeProperty) g.getNamedProperty(IlvAttributeProperty.NAME);
                        if (p != null) {
                            String smin=getAttributeValue(att,scaleMinAttributeName);
                            String smax=getAttributeValue(att,scaleMaxAttributeName);
                            double scalemin = (smin==null)?0:Double.parseDouble(smin);
                            double scalemax = (smax==null)?0:Double.parseDouble(smax);
                            if(scalemin !=0 || scalemax !=0) {
                                if(scalemin !=0) {
                                  themeControl.addTheme(1f / scalemin, layers[il], invisible); 
                                  themeControl.getStyle(layers[il], 1f / scalemin).setVisibleInView(false);
                                }
                                if(scalemax !=0) {
                                  themeControl.addTheme(1f / scalemax, layers[il], visible); 
                                  themeControl.getStyle(layers[il], 1f / scalemax).setVisibleInView(true);
                                  themeControl.getStyle(layers[il], 1).setVisibleInView(false);
                                } else {
                                    themeControl.getStyle(layers[il], 1).setVisibleInView(true);
                                }
                            }
                        }
                    }
                    }
            }
        }
        String getAttributeValue(IlvFeatureAttributeProperty a,String attributeName){
            try {
                return a.getValue(attributeName).toString();
            } catch (IllegalArgumentException e) {
                //this means that the property is not there.
            }
            return null;
        }
        boolean hasAttribute(IlvAttributeInfoProperty p,String attributeName){
            try {
                // does this layer define that attribute ?
               if( p.getAttributeIndex(attributeName) > -1) 
               {
                   return true;
               }
            } catch (IllegalArgumentException e) {
                //this means that the property is not there.
            }
            return false;
        }
    }
static class ColorSetDisplayItem {
    final String value;
    String label;
    public ColorSetDisplayItem(String value) {
       this.value=value;
    }
    public String toString() {
        if(label==null) {
            label=IlvMapUtil.getString(S57LoadAction.class,"S57LoadAction.ColorSet"+value);//$NON-NLS-1$
        }
        return label;
    }
    public String getValue() {
        return value;
    }
  }
  //JV-4656
  ColorSetDisplayItem S52Colorsets[]= {
     new ColorSetDisplayItem("DAY"), //$NON-NLS-1$ // (defined by S52)
     new ColorSetDisplayItem("DUSK"), //$NON-NLS-1$ //(defined by S52)
     new ColorSetDisplayItem("NIGHT") //$NON-NLS-1$ //(defined by S52)
  };
    IlvFeatureSelectorPanel panel;
    TilingParameterPanel tilingPanel;
    JPanel compositePanel;
    JCheckBox useScaleLimits ;
    JCheckBox simplified ;
    JCheckBox showDescriptionText ;
    JComboBox colorset;
    /**
   * Creates an action for the specified view
   * @param view view to add map data to.
   */
  public S57LoadAction(IlvManagerView view)
  {
    super(view);
  }
  /**
   * @see plugins.ImportAction#getSubDirectory()
   */
  protected String getSubDirectory() {
    return IlvMapUtil.getString(getClass(),"S57LoadAction.CDDirectory"); //$NON-NLS-1$
  }
  /**
   * @see plugins.ImportAction#getDataSources(URL[])
   */
  public Enumeration getDataSources(URL urls[]) { 
    return null;
  }
  /**
   * @see plugins.ImportAction#getDataSources(java.lang.String[])
   */
  public Enumeration getDataSources(String fileNames[])  { 
    Vector src=new Vector();
    IlvFeatureSelectorPanel.Feature[] features = panel.getSelectedFeatures();
//  String[] faccCodes = new String[features.length];
          ArrayList ccodes = new ArrayList();
          if (features != null) {
              for (int j = 0; j < features.length; j++) {
                  IlvFeatureSelectorPanel.Feature currentFeature = features[j];
                  IlvFeatureSelectorPanel.Feature currentChild;
                  int nChildren=currentFeature.getChildCount();
                  if(nChildren!=0) {// major
                          for (int i = 0; i < currentFeature.getChildCount(); i++) {
                              currentChild = (IlvFeatureSelectorPanel.Feature)currentFeature.getChildAt(i);
                              ccodes.add(currentChild.getMajorCode() + currentChild.getMinorCode());                
                          }               
                  } else {
              ccodes.add(currentFeature.getMajorCode() + currentFeature.getMinorCode());                
                  }
              }       
          }
      IlvThreadMonitoringData monitorData=new IlvThreadMonitoringData(getMonitor(),fileNames,getActivityDescription(RENDERING) ,0,100); 
     for (int i = 0; i < fileNames.length; i++) {
        IlvDefaultTilableDataSource source = S57DefLess.newIlvS57DataSource(fileNames[i]);
        ColorSetDisplayItem item=(ColorSetDisplayItem)(colorset.getSelectedItem());
        S57DefLess.setRenderingParameters(source,simplified.isSelected(),showDescriptionText.isSelected(),item.getValue());
        source.setAcceptedCodeList((String[])ccodes.toArray(new String[0]));   
        if(simplified.isSelected()) {
        /// S57 must be simplified to use tiling 
            source.setTilingParameters(tilingPanel.isTiling(),tilingPanel.getRows(),tilingPanel.getColumns());
        }
        source.setAreaOfinterest(tilingPanel.getLonMin(),tilingPanel.getLatMin(),tilingPanel.getLonMax(),tilingPanel.getLatMax());
        source.setManager(getView().getManager());
        source.setName(getFormatName() + " (" + new File(fileNames[i]).getName() + ")"); //$NON-NLS-1$ //$NON-NLS-2$
        source.setMonitoringData(monitorData);
        // make use of scale minimum when the data is loaded.
        if(useScaleLimits.isSelected()) {
            source.addDataSourceListener(new ScaleMimimumManager());
        }
        src.add(source);
    }
    return src.elements();
   }
  
  /**
   * @see plugins.ImportAction#approveSelection(File [])
   */
  public boolean approveSelection(File selection[]) {
    IlvFeatureSelectorPanel.Feature[] features = panel.getSelectedFeatures();
    if (features == null || features.length==0){
      JOptionPane.showMessageDialog(getView(),
          IlvMapUtil.getString(S57LoadAction.class,"S57LoadAction.NoFeatureMessage"), //$NON-NLS-1$
          IlvMapUtil.getString(S57LoadAction.class,"S57LoadAction.NoFeatureTitle"),//$NON-NLS-1$
          JOptionPane.ERROR_MESSAGE);
      return false;
    }
    return super.approveSelection(selection);
  }

  /**
   * @see plugins.ImportAction#getExtensions()
   */
  public String [] getExtensions(){
    return new String[]{".000"}; //$NON-NLS-1$
 }
  /**
   * Returns an IlvFeatureSelectorPanel
   * @see plugins.ImportAction#getAccessory()
   */
  public JComponent getAccessory() {
    String filename = "S57FeaturesEN.xml"; //$NON-NLS-1$
    if (compositePanel == null) {
        compositePanel = new JPanel(new BorderLayout());
        panel = new IlvFeatureSelectorPanel(null, filename,"S57");//$NON-NLS-1$
        JScrollPane sp = new JScrollPane(panel);
        compositePanel.add(sp,BorderLayout.CENTER);
        tilingPanel=new TilingParameterPanel(getView(),false);
        simplified = new JCheckBox(IlvMapUtil.getString(getClass(), "S57LoadAction.Simplified"), false); //$NON-NLS-1$
       // Limitation: Prevent using tiling when using non-simplified rendering
        tilingPanel.useTilingBox.setEnabled(simplified.isSelected());
        showDescriptionText = new JCheckBox(IlvMapUtil.getString(getClass(), "S57LoadAction.ShowDescriptionText"), false); //$NON-NLS-1$
        colorset = new JComboBox(S52Colorsets);
        simplified.addChangeListener(new ChangeListener() {
          public void stateChanged(ChangeEvent e) {
              colorset.setEnabled(!simplified.isSelected());
              tilingPanel.useTilingBox.setEnabled(simplified.isSelected());
              // Limitation: Prevent using tiling when using non-simplified rendering
              if(!simplified.isSelected()){
                  tilingPanel.useTilingBox.setSelected(false);
              }
              showDescriptionText.setEnabled(!simplified.isSelected());
          }
        });
        JPanel hintsPanel=new JPanel(new BorderLayout());
        JPanel optionPanel=new JPanel();
        hintsPanel.setBorder(BorderFactory.createTitledBorder(IlvMapUtil.getString(getClass(), "S57LoadAction.RenderingOptions"))); //$NON-NLS-1$
        hintsPanel.add(simplified,BorderLayout.NORTH);
        useScaleLimits = new JCheckBox(IlvMapUtil.getString(getClass(), "S57LoadAction.UseS52ScaleLimits"), false); //$NON-NLS-1$
        hintsPanel.add(useScaleLimits,BorderLayout.SOUTH);
        optionPanel.add(showDescriptionText);
        optionPanel.add(new JLabel(IlvMapUtil.getString(getClass(), "S57LoadAction.Colorset"))); //$NON-NLS-1$
        optionPanel.add(colorset);
        hintsPanel.add(optionPanel,BorderLayout.CENTER);
        compositePanel.add(hintsPanel,BorderLayout.NORTH);
        compositePanel.add(tilingPanel,BorderLayout.SOUTH);
     }
    return compositePanel;
  }
  
  /**
   * @see plugins.ImportAction#getFormatName()
   */
  public String getFormatName() {
    return ilog.views.maps.IlvMapUtil.getString(getClass(),"S57LoadAction.FormatName"); //$NON-NLS-1$
  }
  /**
   * @see plugins.ImportAction#isAvailable()
   */
  public boolean isAvailable() {
    return super.isAvailable() && S57DefLess.isAvailable();
  }
}