package mambo;

import fr.esrf.Tango.DevVarDoubleStringArray;
import fr.esrf.tangoatk.widget.util.chart.JLChart;
import fr.esrf.tangoatk.widget.util.chart.JLDataView;
import fr.esrf.tangoatk.widget.util.chart.JLDataViewOption;
import fr.soleil.TangoHdb.HdbApi.HdbDataBase;

import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;
import javax.swing.*;
import java.awt.*;
import java.sql.SQLException;
import java.text.ParseException;

/**
 *  HDB Attribute Tree viewer
 *  Jean-Luc PONS     2002
 *
 *  Simple TreeNode that builds children on the fly.
 *  The key idea is that getChildCount is always called before
 *  any actual children are requested. So getChildCount builds
 *  the children if they don't already exist.
 */


public class HdbTreeNode extends DefaultMutableTreeNode {

  // Globals
  static public int nbAction = 6;
  static public String[] ItemAction = {"Request data","Plot on Y1","Plot on Y2","Set on X axis","Unselect","Settings"};
  static public final int SELNONE=0;
  static public final int SELY1=1;
  static public final int SELY2=2;
  static public final int SELX=3;
  public static final Color[] defaultColor = {
      Color.red ,
      Color.blue ,
      Color.cyan ,
      Color.green ,
      Color.magenta ,
      Color.orange ,
      Color.pink ,
      Color.yellow };
  static int colorIndex=0;

  // Locals
  private boolean areChildrenDefined = false;
  private int numChildren;
  private String value="";
  private int level=0;
  private int selected=SELNONE;
  private JLChart theGraph=null;  // Handle the the global graph
  private JLDataView theView=null;

  // *****************************************************************************************************************
  // Contruct a Tango Tree (Cannot build root node)
  public HdbTreeNode(String v,int l,JLChart g) {
    value = v;
    level = l;
    theGraph=g;

    // Create a DataView
    if(isLeaf()) {
      theView=new JLDataView();
      theView.setColor( defaultColor[colorIndex % 8] );
      colorIndex++;
    }
  }


  // *****************************************************************************************************************
  // Return true when tree node is a Leaf
  public boolean isLeaf() {
    return level==4;
  }


  // *****************************************************************************************************************
  // Return the number of children and create them if they don't already exists
  public int getChildCount() {
    if (!areChildrenDefined)
      defineChildNodes();
    return (super.getChildCount());
  }

  // *****************************************************************************************************************
  // Add dinamycaly nodes in the tree when the user open a branch.
  private void defineChildNodes() {

    //  The flag areChildrenDefined must set before defining children
    // Otherwise you get an infinite recursive loop, since add results
    // in a call to getChildCount.

    areChildrenDefined = true;
    int i;
    String[] list=null;

    switch (level) {
        case 0:
          // Get the list of domain
          list = new String[2];
          list[0] = "jlp";
          list[1] = "sr";
          break;
        case 1:
          // Get the list of family
          list = new String[2];
          list[0] = "test";
          list[1] = "d-irm";
          break;
        case 2:
          // Get the list of member
          list = new String[4];
          list[0] = "1";
          list[1] = "2";
          list[2] = "3";
          list[3] = "id22";
          break;
        case 3:
          // Get the list of attribute
          list = new String[15];
          list[0] = "att_un";
          list[1] = "att_deux";
          list[2] = "att_trois";
          list[3] = "att_quatre";
          list[4] = "T1";
          list[5] = "T2";
          list[6] = "T3";
          list[7] = "T4";
          list[8] = "T5";
          list[9] = "T6";
          list[10] = "T7";
          list[11] = "T8";
          list[12] = "T9";
          list[13] = "Position";
          break;
    }

    if (list != null) {
        numChildren = list.length;
        for (i = 0; i < numChildren; i++)
           add(new HdbTreeNode(list[i],level+1,theGraph));
    } else {
        numChildren = 0;
    }



  }

  // *****************************************************************************************************************
  public String toString() {
    return (value);
  }

  // *****************************************************************************************************************
  // Return the complete path of the node
  public TreePath getCompletePath() {
    int i;

    // Construct the path
    HdbTreeNode node = this;
    HdbTreeNode[] nodes = new HdbTreeNode[node.level + 1];
    for (i = nodes.length - 1; i >= 0; i--) {
      nodes[i] = node;
      node = (HdbTreeNode) node.getParent();
    }
    return new TreePath(nodes);

  }

  // *****************************************************************************************************************
  public String getAttributeName() {

    String ret = "";
    int i;

    // Construct full string
    HdbTreeNode node = this;
    HdbTreeNode[] nodes = new HdbTreeNode[node.level];
    for (i = nodes.length; i>0; i--) {
      nodes[i-1] = node;
      node = (HdbTreeNode) node.getParent();
    }
    for (i = 0; i < nodes.length; i++) {
      ret += nodes[i].toString();
      if(i<nodes.length-1) ret += "/";
    }
    return ret;

  }

  // *****************************************************************************************************************
  // Returns possible action for the node as a boolean array
  // Returns null when no action possible
  // ret[0] =  Request data
  // ret[1] =  Plot on Y1
  // ret[2] =  Plot on Y2
  // ret[3] =  Set on X axis
  // ret[4] =  Unselect
  // ret[5] =  Settings
  public boolean[] getAction() {

    boolean[] ret = null;

    if(isLeaf()) {
      ret = new boolean[nbAction];
      for(int i=0;i<nbAction;i++) ret[i]=false;
      ret[0]= true;
      ret[1]= (selected != SELY1) && hasData();
      ret[2]= (selected != SELY2) && hasData();
      ret[3]= (selected != SELX) && hasData();
      ret[4]= (selected != SELNONE);
      ret[5]= hasData();
    } else {
      return null;
    }

    return ret;

  }

  public boolean hasData() {
    if( isLeaf() )
      return theView.getDataLength()>0;

    return false;
  }

  public int getDataLength() {
    if( isLeaf() )
      return theView.getDataLength();

    return 0;
  }

  public JLChart getGraph() {
    return theGraph;
  }

  // Retrieve Data form HDB and fill internal structure.
  // Retuns null when OK or an error String when failed.
  public String retrieveData(QueryInfo qi,HdbDataBase db) {

    String param[] = new String[3];
    DevVarDoubleStringArray ret;

    // Remove the view from the graph
    setSelected(SELNONE);
    theView.reset();

    try {
      param[0] = getAttributeName();
      param[1] = qi.getStartDate();
      param[2] = qi.getStopDate();
      ret = db.getAttributeScalarDataBetweenDates(param);
    } catch (SQLException e) {
      return "Cannot get data for " + getAttributeName() + "\n" + e.getMessage();
    }

    int nb = ret.dvalue.length;

    System.out.println(getAttributeName() + " : " + nb + " datas.");

    try {

      for( int i=0 ; i<nb;i++ )
        theView.add( (double)DateUtil.dateToTime(ret.svalue[i]) ,  ret.dvalue[i] );

    } catch (ParseException e) {
      theView.reset();
      return "Error during date conversion\n"+e.getMessage();
    }

    return null;
  }

  public int getSelected() {
    return selected;
  }

  public void setSelected(int s) {

	 switch( s ) {

	 case SELNONE:
	   switch( selected ) {
	     case SELX:
		 theGraph.getXAxis().removeDataView( theView );
		 break;
	     case SELY1:
		 theGraph.getY1Axis().removeDataView( theView );
		 break;
	     case SELY2:
		 theGraph.getY2Axis().removeDataView( theView );
		 break;
	   }
	   break;

	 case SELX:
	   switch( selected ) {
	     case SELY1:
		 theGraph.getY1Axis().removeDataView( theView );
		 break;
	     case SELY2:
		 theGraph.getY2Axis().removeDataView( theView );
		 break;
	   }
	   theGraph.getXAxis().addDataView( theView );
	   break;

	 case SELY1:
	   switch( selected ) {
	     case SELX:
		 theGraph.getXAxis().removeDataView( theView );
		 break;
	     case SELY2:
		 theGraph.getY2Axis().removeDataView( theView );
		 break;
	   }
	   theGraph.getY1Axis().addDataView( theView );
	   break;

	 case SELY2:
	   switch( selected ) {
	     case SELX:
		 theGraph.getXAxis().removeDataView( theView );
		 break;
	     case SELY1:
		 theGraph.getY1Axis().removeDataView( theView );
		 break;
	   }
	   theGraph.getY2Axis().addDataView( theView );
	   break;

	 }

     theView.setName(this.getAttributeName());
     theGraph.repaint();
	 selected=s;

   }

  public void showOptions(JFrame parent) {
     if( hasData() ) {
       JLDataViewOption dlg = new JLDataViewOption(parent,theGraph,theView);
       dlg.setVisible(true);
     }
  }

}
