import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;

import javax.swing.border.EmptyBorder;

import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.border.TitledBorder;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import javax.swing.border.LineBorder;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.beans.XMLDecoder;
import java.beans.XMLEncoder;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.URL;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.imageio.ImageIO;
import javax.swing.border.*;
import javax.swing.event.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.filechooser.FileSystemView;
import javax.swing.table.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import java.util.List;
import java.awt.*;

import java.awt.*;
import java.beans.DefaultPersistenceDelegate;
import java.beans.Encoder;
import java.beans.Statement;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.Reader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;

import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreeNode;

// MVC   modelisation  visualization  command

public class jdialog03 extends JDialog 
{
	private static JTable table;
	private JTree tree;
///	private static DefaultTableModel xxxmodel;
	private boolean close_Jdialog = false;
	private TreeModel model;
	private List<TreeNode[]> expanded;
	private JButton btn_load_tree;
	private JButton btn_save_tree;
	private JButton btn_load_table;
	private JButton btn_save_table;
	
	private JButton btn_analyse;
	
	
	private File file = new File("TableModel.xml");	
	private DefaultTableModel tableModel; 
	private JFileChooser myJFileChooser = new JFileChooser(new File(".")); 
	
//	private Class_plan intermediaire;   
	
	private ArrayList<String> tree_node = new ArrayList<String>();
	
	private Class_plan intermediaire = new Class_plan();
	
	private WriteXML WRITE_XML; 
	private ReadXML READ_XML; 
	
	private ArrayList<String> tree_datas = new ArrayList<String>();
	
	private ArrayList<String> tmp_tree_datas = new ArrayList<String>();
	
	DefaultMutableTreeNode root;
	
	MyTreeModelPlan model_load_datas;
	boolean flag_load_datas = false;
	
	public jdialog03(JFrame f, boolean modal) 
	{
       super(f, modal);
       

       WRITE_XML = new WriteXML();
       READ_XML = new ReadXML();
       
       
       // fermer la fenetre
       addWindowListener(new java.awt.event.WindowAdapter() 
       {
           public void windowClosing(java.awt.event.WindowEvent e) 
           {
               //serialize();
        	   dispose();
           }
       });
       
       expanded = new ArrayList<TreeNode[]>();
       
       init();
     
	}
  
	private void init()
	{
	  	setResizable( false );
		setBounds(100, 100, 926, 550);
		setTitle("version 3 - Test definition - debug ...");
		getContentPane().setLayout(null);
     	
		ImageIcon icon = null;
		icon = createImageIcon("resources/settings.png", "");
		setIconImage( icon.getImage() );
		
		setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
		
		JScrollPane scrollPane_2 = new JScrollPane();
		scrollPane_2.setBounds(50, 39, 183, 194);
		getContentPane().add(scrollPane_2);
		
		
		//root = new DefaultMutableTreeNode("Plan");
		
		model_load_datas = new MyTreeModelPlan();
		// on charge seulement le node principal
		model_load_datas.load(flag_load_datas, tree_datas, intermediaire);
		flag_load_datas = !flag_load_datas;
	    tree = new JTree(model_load_datas);

/*		
	    DefaultMutableTreeNode category;
	    DefaultMutableTreeNode book;
		 
	   
	   
	    category = new DefaultMutableTreeNode("xxxxxxxxxx");
	    root.add(category);
		 
	    category.add(new DefaultMutableTreeNode("bli"));
  		category.add(new DefaultMutableTreeNode("zorbi")); 
		 
	    category = new DefaultMutableTreeNode("yyyyyyyyyyyyyyyyyyyyyyy");
	    root.add(category);
		 
	    category.add(new DefaultMutableTreeNode("Tim Lindholm"));
  		category.add(new DefaultMutableTreeNode("Frank Yellin")); 
*/		
		
		//tree = new JTree(root);
		//tree.setRowHeight(45);
		//tree = new JTree();
		
		tree.setComponentPopupMenu(new SelectionTreePopupMenu_bis(intermediaire));
		
		scrollPane_2.setViewportView(tree);
		 
		tree.addMouseListener(new MouseAdapter() 
		{
		      public void mouseClicked(MouseEvent me) 
		      {
		    	  doMouseClicked(me);
		      }
	    });
		
		JScrollPane scrollPane = new JScrollPane();
		scrollPane.setBounds(294, 39, 532, 159);
		getContentPane().add(scrollPane);
		
		String[] columnNames =  {"Test", "Descrition" , "rien"};
	     
	    /*Object[][] data = {
							{null, null, null},
							{null, null, null},
							{null, null, null},
							{null, null, null},
							{null, null, null},
						  };
		*/
	    Object[][] data = {	{ "", "", ""}  };
	    
		tableModel = new DefaultTableModel(data, columnNames)
		{
	        @Override
	        public boolean isCellEditable(int row, int column)
	        {
	            // make read only fields except column 0,13,14
	            return column == 1 || column == 2 ;
	        }
	    };
		
	    table = new JTable(tableModel);
	    table.setRowHeight(30);
	    table.setFont(new Font("Serif", Font.BOLD, 20));
	    
	    table.addFocusListener(new FocusAdapter() 
	    {
	        @Override
	        public void focusLost(FocusEvent e) 
	        {
	            //if (e.getOppositeComponent().getParent() != table) 
	            //{
	               // loseCellFocus();
	            	System.out.println("Lost focus");
	            	
	            	
	            	String retour = table.getValueAt(0, 0).toString();
	            	
	            	//int row = table.getSelectedRow();
	            	String test_str = table.getModel().getValueAt(0, 0).toString();
	            	String descrition_str = table.getModel().getValueAt(0, 1).toString();
	            	String rien_str = table.getModel().getValueAt(0, 2).toString();
	            	
	            	System.out.println(test_str + " " + descrition_str + " " + rien_str );
	            	
	            	TestPlan obj = intermediaire.GetSequenceNamed(test_str);
	            	
	            	obj.setTextchamp1(descrition_str);
	            	obj.setTextchamp2(rien_str);
	            	
	           // }
	        }
	    });
	/*    
		JTable table = new JTable(); 
        Object[] columns = {"Id","First Name","Last Name","Age"};
        DefaultTableModel model = new DefaultTableModel();
        model.setColumnIdentifiers(columns);
        
        // set the model to the table
        table.setModel(model);
        
        table.setBackground(Color.LIGHT_GRAY);
        table.setForeground(Color.black);
        //Font font = new Font("",1,22);
        //table.setFont(font);
        //table.setRowHeight(30);
*/
	    
		scrollPane.setViewportView(table);

		/*******************/
		
		btn_load_tree  = new JButton("Load");
		btn_load_tree.addActionListener(new ActionListener() 
		{
			public void actionPerformed(ActionEvent arg0) 
			{
				System.out.println("Btn load  \n");
				
				loadJtree();
				
				//model_load_datas.load(flag_load_datas);
				//flag_load_datas = !flag_load_datas;
				//deSerialize();
			   
				
			}
		});
		btn_load_tree.setBounds(50, 257, 89, 23);
		getContentPane().add(btn_load_tree);
				
		btn_save_tree = new JButton("Save");
		btn_save_tree.addActionListener(new ActionListener() 
		{
			public void actionPerformed(ActionEvent arg0) 
			{
				System.out.println("Btn save  \n");
				saveJtree();
				//serialize();
			}
		});
		btn_save_tree.setBounds(161, 257, 89, 23);
		getContentPane().add(btn_save_tree);
		
		/*******************/
		
		btn_load_table  = new JButton("Query");
		btn_load_table.addActionListener(new ActionListener() 
		{
			public void actionPerformed(ActionEvent arg0) 
			{
				System.out.println("Btn Query \n");
				/*
				TreeModel model = tree.getModel();
				
				String pipo = getTreeText(model, model.getRoot(), "");
				
				String[] parts = pipo.split(" ");
				
				System.out.println(getTreeText(model, model.getRoot(), ""));
				
				System.out.println("-------------------------------------");
				
				TreeNode root = (TreeNode) tree.getModel().getRoot();
			    visitAllNodes(root);
			    
			    System.out.println("-------------------------------------");
							    
			    traverse(tree);
				
			    System.out.println("-------------------------------------");
				
			    
			    
				
			    */
			
				System.out.println("-------------------------------------");
				
				explore_tree(model);
				
				System.out.println("-------------------------------------");
				
			    ArrayList<TestPlan>  objTree  = new ArrayList<TestPlan>();
			    objTree = intermediaire.getTreeChild();
                split02.myArea.append(" Nb tree : " + objTree.size() + "\n");

                for(int i = 0; i < objTree.size(); i++)
                {
                	String type = objTree.get(i).getType();
    				String val1 = objTree.get(i).getTextchamp1();
    	        	String val2 = objTree.get(i).getTextchamp2();
    	        	 
                	System.out.println(" TRACE: " + type + "  " + val1 + " " + val2);
                }

                
                
			
			}
		});
		btn_load_table.setBounds(450, 257, 89, 23);
		getContentPane().add(btn_load_table);
				
		btn_save_table = new JButton("Save");
		btn_save_table.addActionListener(new ActionListener() 
		{
			public void actionPerformed(ActionEvent arg0) 
			{
				System.out.println("Btn save table  \n");
				
				//saveTable(file); 
			}
		});
		btn_save_table.setBounds(550, 257, 89, 23);
		getContentPane().add(btn_save_table);
		
		/*******************/
		
		
		btn_analyse  = new JButton(" ++++ ");
		btn_analyse.addActionListener(new ActionListener() 
		{
			public void actionPerformed(ActionEvent arg0) 
			{
				System.out.println("Btn analyse  \n");
				
				//TreeModel model = tree.getModel();
				//tableModel.setValueAt( "Zorro" , 0, 0);
				
				ArrayList<TestPlan>  list_tree_nodes  = new ArrayList<TestPlan>();
				list_tree_nodes = intermediaire.getTreeElement();
                split02.myArea.append(" Nb tree children  : " + list_tree_nodes.size() + "\n");

				
//				tableModel.addRow(new Object[]{null,null,null});
/*				
				TreeModel model = tree.getModel();
				System.out.println(getTreeText(model, model.getRoot(), ""));
				
				System.out.println("******************************");
				printDescendants(root);
				 
				 traverse(tree);
				 
				 if(tree_node.size() != 0)
				 {
					 for(int i = 0; i < tree_node.size() ; i++)
					 {
						 //if(tree_node.get(i).indexOf("--") != -1)
						 //{
							 tableModel.setValueAt( tree_node.get(i) , i, 0);
						 //}
					 }	 
				 }
				 else
				 {
			    	  String msg = String.format("ERROR: Node not find !.");
			          JOptionPane.showMessageDialog(tree, msg, "Message", JOptionPane.ERROR_MESSAGE);

				 }
*/					 
				// split02.myArea.append(" [ INFO ]: blabla " + "\n");
				
				//getModel()
				// https://imss-www.upmf-grenoble.fr/prevert/Prog/Java/swing/JTree.html
				// https://www.rgagnon.com/javadetails/java-0313.html    traverse 
				
			}
		});
		btn_analyse.setBounds(250, 257, 89, 23);
		getContentPane().add(btn_analyse);
		
		/*******************/
		
		JSeparator separator = new JSeparator();
		separator.setBounds(240, 302, 440, 2);
		getContentPane().add(separator);
	
		/*******************/
		
		JButton btn_ok = new JButton("OK");
		btn_ok.addActionListener(new ActionListener() 
		{
			public void actionPerformed(ActionEvent arg0) 
			{
				close_Jdialog = false;
				System.out.println("Btn Cancel  \n");
				dispose();
			}
		});
		btn_ok.setBounds(135, 391, 89, 23);
		getContentPane().add(btn_ok);
	
		/*******************/
		
		JButton btn_cancel = new JButton("Cancel");
		btn_cancel.addActionListener(new ActionListener() 
		{
			public void actionPerformed(ActionEvent e) 
			{
				close_Jdialog = false;
				System.out.println("Btn Cancel  \n");
				dispose();
			}
		});
		btn_cancel.setBounds(359, 391, 89, 23);
		getContentPane().add(btn_cancel);
		
		/*******************/
	}
	
	
	private  String getTreeText(TreeModel model, Object object, String indent) 
	{
	    String myRow = indent + object + "\n";
	    for (int i = 0; i < model.getChildCount(object); i++) {
	        myRow += getTreeText(model, model.getChild(object, i), indent + "  ");
	    }
	    return myRow;
	}
	
	private void saveStatus() 
	{
        //save the expanded Nodes:
        expanded = new ArrayList<TreeNode[]>();
        collectStatusInfo(model.getRoot());
	}

	private void restoreStatus() 
	{
        //expand the saved Nodes:
        for (int i = expanded.size() - 1; i > -1; i--) 
        {
        	TreeNode[] ar = expanded.get(i);
	        tree.expandPath(new TreePath(ar));
        }
	}

	private void collectStatusInfo(final Object o) 
	{
		int cc = model.getChildCount(o);
	    for (int i = 0; i < cc; i++) 
	    {
	    	DefaultMutableTreeNode child = (DefaultMutableTreeNode) model.getChild(o, i);
	        TreeNode[] ar = child.getPath();
	        if (!model.isLeaf(child) && tree.isExpanded(new TreePath(ar))) 
	        {
	        	expanded.add(ar);
	            collectStatusInfo(child);
	        }
        }
	}
	
	
	
	
	// https://wiki.byte-welt.net/wiki/JTree_Zustand_speichern
	public void serialize() 
	{
		try 
		{
			XMLEncoder o = new XMLEncoder(new BufferedOutputStream(new FileOutputStream("tree.xml")));
	        o.writeObject(tree.getModel());
	        o.writeObject(expanded);
	        o.close();
        } 
		catch (IOException e) 
		{
			e.printStackTrace();
        }
	}

	@SuppressWarnings("unchecked")
	private void deSerialize() 
	{
        try 
        {
        	XMLDecoder d = new XMLDecoder(new BufferedInputStream(new FileInputStream("tree.xml")));
	        tree.setModel((TreeModel) d.readObject());
	        expanded = (List<TreeNode[]>) d.readObject();
	        d.close();
        } 
        catch (FileNotFoundException ex) 
        {
	    }
	}
    
	public ImageIcon createImageIcon(String path,  String description) 
	{
		URL imgURL = getClass().getResource(path);

		if (imgURL != null)
		{
  			return new ImageIcon(imgURL, description);
		} 
		else 
		{
			System.err.println("Couldn't find file: " + path);
			return null;
		}
	}
	
	/******************************************/
	
	private void saveTable() 
	{
        if (myJFileChooser.showSaveDialog(this) == JFileChooser.APPROVE_OPTION ) 
        {
            saveTable(myJFileChooser.getSelectedFile());
        }
    }
     
    private void saveTable(File file) 
    {
        try 
        {
            ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(file));
            out.writeObject(tableModel.getDataVector());
            out.writeObject(getColumnNames());
            out.close();
        }
        catch (Exception ex) 
        {
            ex.printStackTrace();
        }
    }
    
    private Vector<String> getColumnNames() 
    {
        Vector<String> columnNames = new Vector<String>();
        for (int i = 0; i < table.getColumnCount(); i++)
            columnNames.add(table.getColumnName(i) );
        return columnNames;
    }
    
    
    private void loadJtree() 
	{
    	/*
    	JFileChooser jfc = new JFileChooser(FileSystemView.getFileSystemView().getHomeDirectory());
		jfc.setDialogTitle("Select XML file document");
		jfc.setAcceptAllFileFilterUsed(false);
		FileNameExtensionFilter filter = new FileNameExtensionFilter("Available file", "xml" );
		jfc.addChoosableFileFilter(filter);
    	
    	if (jfc.showOpenDialog(this) ==  JFileChooser.APPROVE_OPTION )
    	{
    		jfc.getSelectedFile();
    		loadJtree(jfc.getSelectedFile());
    	}*/
    	
    	
    	 JFileChooser chooser = new JFileChooser();
    	 chooser.setDialogTitle("Choice XML file");
    	 FileNameExtensionFilter filter = new FileNameExtensionFilter( "XML file", "xml" );
    	 chooser.setFileFilter(filter);
    	 
    	 int returnVal = chooser.showOpenDialog(this);
    	 if(returnVal == JFileChooser.APPROVE_OPTION) 
    	 {
    	       //System.out.println("You chose to open this file: " + chooser.getSelectedFile().getName());
    	       
    	       File selectedFile = chooser.getSelectedFile();
    	       //System.out.println(selectedFile.getParent());
    	       //System.out.println(selectedFile.getName());
    	       //System.out.println(selectedFile.getPath());   /// ce que je veux
    	       //System.out.println(selectedFile.getAbsoluteFile());
    	       
    	       tree_datas = READ_XML.Tree_ReadXML( selectedFile.getPath() );
    	       
    	       model_load_datas.load(flag_load_datas, tree_datas, intermediaire);
			   flag_load_datas = !flag_load_datas;
    	       
    	      
    	    }
    	
    }
    
   
    private void saveJtree() 
	{
    
    	
    	JFileChooser fileChooser = new JFileChooser();
    	fileChooser.setDialogTitle("Specify a file to save");   
    	 
    	// fileChooser.setSelectedFile(new File("myfile.xml"));
    	fileChooser.setFileFilter(new FileNameExtensionFilter("xml file","xml"));
    	
    	int userSelection = fileChooser.showSaveDialog(this);
    	 
    	if (userSelection == JFileChooser.APPROVE_OPTION) 
    	{
    	    File fileToSave = fileChooser.getSelectedFile();
    	    System.out.println("Save as file: " + fileToSave.getAbsolutePath());
    	    
    	    // collecte les datas
    	    
    	    tmp_tree_datas.clear();
    	    
    	    ArrayList<TestPlan>  objTree  = new ArrayList<TestPlan>();
		    objTree = intermediaire.getTreeChild();

            for(int i = 0; i < objTree.size(); i++)
            {
            	String type = objTree.get(i).getType();
            	String sequence = objTree.get(i).getSequence();
				String val1 = objTree.get(i).getTextchamp1();
	        	String val2 = objTree.get(i).getTextchamp2();
	        	if(val1.equals("") && val2.equals("") )
	        	{
	        		tmp_tree_datas.add(sequence);
	        	}
	        	else
	        	{	
	        		tmp_tree_datas.add(sequence + "-" + val1 + "-" + val2);
	        	}
	        	System.out.println(" DATA collection to save in file: " + type + "-" + val1 + "-" + val2);
            }
    	    
    	    WRITE_XML.Tree_WirteXML(tmp_tree_datas, fileToSave.getAbsolutePath());
    	    
    	}
    	
    	/*JFileChooser fileChooser = new JFileChooser();
        int retval = fileChooser.showSaveDialog(save);
        if (retval == JFileChooser.APPROVE_OPTION) 
        {
	          File file = fileChooser.getSelectedFile();
	          if (file == null) 
	          {
	            return;
	          }
	          if (!file.getName().toLowerCase().endsWith(".txt")) {
	            file = new File(file.getParentFile(), file.getName() + ".txt");
	          }
	          try 
	          {
	            textArea.write(new OutputStreamWriter(new FileOutputStream(file),
	                "utf-8"));
	            Desktop.getDesktop().open(file);
	          } 
	          catch (Exception e) 
	          {
	            e.printStackTrace();
	          }
        }*/
    	
	}
    
    private void loadTable() 
	{
    	if (myJFileChooser.showOpenDialog(this) ==  JFileChooser.APPROVE_OPTION )
	            loadTable(myJFileChooser.getSelectedFile());
    }
	 
    private void loadTable(File file) 
	{
        try 
        {
        	ObjectInputStream in = new ObjectInputStream( new FileInputStream(file));
	        Vector rowData = (Vector)in.readObject();
	        Vector columnNames = (Vector)in.readObject();
	        tableModel.setDataVector(rowData, columnNames);
	        in.close();
        }
        catch (Exception ex) 
        {
	        ex.printStackTrace();
	    }
    }
	
	/******************************************/
	
    public  void printDescendants(TreeNode root) 
    {
        System.out.println(root);
        Enumeration children = root.children();
        if (children != null) 
        {
          while (children.hasMoreElements()) 
          {
            printDescendants((TreeNode) children.nextElement());
          }
        }
    }
    
    public static void visitAllNodes(TreeNode node) 
    {
        System.out.println(node);
        if (node.getChildCount() >= 0) {
          for (Enumeration e = node.children(); e.hasMoreElements();) {
            TreeNode n = (TreeNode) e.nextElement();
            visitAllNodes(n);
          }
        }
      }
    
    public void traverse(JTree tree) 
    { 
        TreeModel model = tree.getModel();
        if (model != null) 
        {
            Object root = model.getRoot();
            System.out.println(root.toString());
            node_hierarchie(model,root);    
        }
        else
        {	
           System.out.println("Tree is empty.");
        }   
    }
        
    public void node_hierarchie(TreeModel model, Object o)
    {
    	
    	tree_node.clear();
    	
        int  cc;
        cc = model.getChildCount(o);
        for( int i=0; i < cc; i++) 
        {
        	Object child = model.getChild(o, i );
        	if (model.isLeaf(child))
        	{	
        		System.out.println(child.toString());
        		tree_node.add(child.toString());
        	}
        	else 
        	{
        		System.out.print(child.toString()+"--");
        		tree_node.add(child.toString()+"--");
        		node_hierarchie(model,child); 
        	}	
           

            
        }
    } 
    
    public void explore_tree(TreeModel model)
    {
    	
    	 Object alpha = model.getRoot();
         String root_str = alpha.toString();
         System.out.println(root_str);
         
         int cpt = 0;
         
         //TreeModel model = tree.getModel();
         //Object alpha =  model.getRoot();
         
         //List<String>[] arrayOfList = new List[100];
         //List<String> l1 = new ArrayList<String>();

         //String valeurs[] = new String[10];
         
         ArrayList<String> array = new ArrayList<String>();
         
         String store[] = new String[10];
         
         for(int i = 0; i < ((DefaultMutableTreeNode) alpha).getChildCount() ; i++) 
         {
             DefaultMutableTreeNode child = (DefaultMutableTreeNode) ((DefaultMutableTreeNode) alpha).getChildAt(i);
             String noeud = child.getUserObject().toString();
             
             System.out.println(noeud);
         
             array.add(noeud);
             store[cpt] = noeud;
             cpt = cpt + 1; 
             
             for(int j = 0; j < child.getChildCount() ; j++) 
             {
                 DefaultMutableTreeNode aaachild = (DefaultMutableTreeNode) child.getChildAt(j);
                 String sub = aaachild.getUserObject().toString();
                 
                 TestPlan obj = intermediaire.GetSequenceNamed(sub);
 				 String val1 = obj.getTextchamp1();
 	        	 String val2 = obj.getTextchamp2();
 	        	 
 	        	 System.out.println(sub + "-" + val1 + "-" + val2);
 	        	 
 	        	 store[cpt] = sub + "-" + val1 + "-" + val2;
 	        	 array.add(sub + "-" + val1 + "-" + val2);
 	        	 
 	        	 cpt = cpt + 1; 
 	        	
             }
             
             
            
         }
         
        // ArrayList<String> tmp_tree_datas = new ArrayList<String>();
/*
         tmp_tree_datas.add("aaa");
         tmp_tree_datas.add("un-aze-qsd");
         tmp_tree_datas.add("bbb");
         tmp_tree_datas.add("deux-pgh-145");
         tmp_tree_datas.add("trois-tyg-bpio");
         */
         
        // WRITE_XML.xxxWirteXML(tmp_tree_datas);

        // ArrayList<String> load_tree_datas = new ArrayList<String>();
         
        // tree_datas = READ_XML.Tree_ReadXML("bidule.xml");

         
        // WRITE_XML.aaaWirteXML();
         
         //READ_XML.aaaReadXML();
         
        // aaa
        // un-aze-qsd
        // bbb
        // deux-pgh-145
        // trois-tyg-bpio
         
         // Java   XML & JSON 
         
 /*        
         <Tree>
            <element category="node">
            	<name>blabla</name>
            	<val1>none</val1>
            	<val2>none</val2>
            </element>
            <element category="child">
               	<name>coco</name>
            	<val1>un</val1>
            	<val2>deux</val2>
            </element>
			<element category="child">
               	<name>trois</name>
            	<val1>123</val1>
            	<val2>aze</val2>
            </element>
            <element category="node">
            	<name>zarby</name>
            	<val1>none</val1>
            	<val2>none</val2>
            </element>
            <element category="child">
               	<name>alpha</name>
            	<val1>I2C</val1>
            	<val2>pipotron</val2>
            </element>
       	 </Tree>
*/         
    }
    
	public void doMouseClicked(MouseEvent me) 
	{
		TreePath TreePathObj = tree.getPathForLocation(me.getX(), me.getY());
		
		if(TreePathObj != null)
		{	
			Object pathString[] = TreePathObj.getPath();
		
			String value = "";
			String s = "";
			String str_concate = "";

			for (int i = 0; i < pathString.length ; i++) 
			{
				str_concate+=pathString[i] + ":";
			}	

			// nb d'ocuurence *
			int nb_occurence = str_concate.length() - str_concate.replace(":", "").length();
			
			System.out.println("----->  " + str_concate + " " + nb_occurence );   
			
			if(nb_occurence == 3)
			{
				// enlever le dernier caractere du path 
				String str_tmp = str_concate.substring(0, str_concate.length()-1); 
				// decoupe
				String[] parts = str_tmp.split(":");
				
				System.out.println(" Selection children " + parts[2] );   
				tableModel.setValueAt(parts[2], 0, 0);
				
				//System.out.println(" Selection children " + parts[1]);   
				TestPlan obj = intermediaire.GetSequenceNamed(parts[2]);
				String val1 = obj.getTextchamp1();
	        	String val2 = obj.getTextchamp2();
				tableModel.setValueAt(val1, 0, 1);
				tableModel.setValueAt(val2, 0, 2);
			}
			
			else
			{
				tableModel.setValueAt("", 0, 0);
				tableModel.setValueAt("", 0, 1);
				tableModel.setValueAt("", 0, 2);
			}
			
		}
		else
		{
			System.out.println(" Jtree area ");   
		}
 	
	}
  
}

class SelectionTreePopupMenu_bis extends JPopupMenu 
{
	  protected TreePath path;

	  int NODE_MAXIMUM_LEVELS = 2;
	  
	 // Class_plan intermediaire = new Class_plan();

	  int level = 0;
	  int sublevel = 0;
	  
	  protected SelectionTreePopupMenu_bis(Class_plan intermediaire) 
	  {
	    super();

	     // intermediaire.addSequence(new TestPlan());
	    
	    add("add child node").addActionListener(e -> 
	    {
	      JTree tree = (JTree) getInvoker();
	      TreePath path = tree.getSelectionPath();
	      //if (path.getPathCount() <= NODE_MAXIMUM_LEVELS) 
	      //{
		      if(path != null )
		      {
		    	  if (path.getPathCount() <= NODE_MAXIMUM_LEVELS) 
		    	  {
		    		  DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
		    		  DefaultMutableTreeNode self = (DefaultMutableTreeNode) path.getLastPathComponent();
		    		  DefaultMutableTreeNode child = new DefaultMutableTreeNode("New child node");
		    		  self.add(child);
		    		  model.reload(self);
		  
		    		  Object pathString[] = path.getPath();
		    		  int n = pathString.length;
		    		  String type = "";
		    		  		    		  
		    		  switch(n) 
		    		  {
			             case 1 :
			            	 		type = "test";
			            	 		level = level + 1;
			            	 		System.out.println(" [Infos]:  level ---> " + type + " " + level);
			            	 		break;
			             case 2 :
			            	 		type = "subtest";
			            	 		sublevel = sublevel + 1;
			            	 		 System.out.println(" [Infos]:  ---> " + type + " " + sublevel);
			            	 		break;
			             default :
			            	 		System.out.println("Invalid choice");
		    		  }
		    			
		    		  intermediaire.addSequence(new TestPlan(type, level, "New child node", "", "") );
		    		  //System.out.println(" [Infos]:  ---> " + type + " " + level);
		    		  
		    	  }
		    	  else 
			      {
			    	  String message = String.format("ERROR: Maximum levels of %d exceeded.", NODE_MAXIMUM_LEVELS);
			          JOptionPane.showMessageDialog(tree, message, "add node", JOptionPane.ERROR_MESSAGE);
			      }
		    	  
		      }
		      else
		      {
		    	  String message = String.format("ERROR: Please , select tree node !. ");
		 	      JOptionPane.showMessageDialog(tree, message, "add child node", JOptionPane.ERROR_MESSAGE);
		      }
		      
	      //	graph_line.addLines( new LineObj((int)StartPoint.getX(), (int)StartPoint.getY(), (int)EndPoint.getX(), (int)EndPoint.getY() , Color.BLUE ) );
 		      
	      // or: model.insertNodeInto(child, self, self.getChildCount());
	      //}
	      //else 
	      //{
	    //	  String message = String.format("ERROR: Maximum levels of %d exceeded.", NODE_MAXIMUM_LEVELS);
	     //     JOptionPane.showMessageDialog(tree, message, "add node", JOptionPane.ERROR_MESSAGE);
	     // }
		      
	    });
	    
	    addSeparator();
	    
	    add("insert preceding sibling node").addActionListener(e -> 
	    {
	      JTree tree = (JTree) getInvoker();
	      DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
	      DefaultMutableTreeNode self = (DefaultMutableTreeNode) path.getLastPathComponent();
	      DefaultMutableTreeNode parent = (DefaultMutableTreeNode) self.getParent();
	      DefaultMutableTreeNode child = new DefaultMutableTreeNode("New preceding sibling");
	      int index = model.getIndexOfChild(parent, self);
	      parent.insert(child, index);
	      model.reload(parent);
	      // or: model.insertNodeInto(child, parent, index);
	    });
	    
	    add("insert following sibling node").addActionListener(e -> 
	    {
	      JTree tree = (JTree) getInvoker();
	      DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
	      DefaultMutableTreeNode self = (DefaultMutableTreeNode) path.getLastPathComponent();
	      DefaultMutableTreeNode parent = (DefaultMutableTreeNode) self.getParent();
	      DefaultMutableTreeNode child = new DefaultMutableTreeNode("New following sibling");
	      int index = model.getIndexOfChild(parent, self);
	      parent.insert(child, index + 1);
	      model.reload(parent);
	      // or: model.insertNodeInto(child, parent, index + 1);
	    });
	    
	    
	    add("Remove").addActionListener(e -> 
	    {
	    	  DefaultMutableTreeNode node = (DefaultMutableTreeNode) path.getLastPathComponent();
		      if (!node.isRoot()) 
		      {
		        JTree tree = (JTree) getInvoker();
		        DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
		        model.removeNodeFromParent(node);
		      }
	    });
		    
	    add("Edit").addActionListener(e -> 
	    {
	    	JTextField textField = new JTextField(); //24
	    	Object node = path.getLastPathComponent();
		      
	    	DefaultMutableTreeNode leaf = (DefaultMutableTreeNode) node;
	    	textField.setText(leaf.getUserObject().toString());
	    	JTree tree = (JTree) getInvoker();
	        
	    	if( !textField.getText().equals("Plan"))
	    	{	
		    	int ret = JOptionPane.showConfirmDialog(tree, textField, "edit", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
		    	if (ret == JOptionPane.OK_OPTION) 
		    	{
		    		Optional.ofNullable(textField.getText())
		            .filter(str -> !str.trim().isEmpty())
		            .ifPresent(str -> {
		              DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
		              String old_sequence = leaf.getUserObject().toString();
		              model.valueForPathChanged(path, str);

		              // mise à jour de la database
		             
		              TestPlan obj = intermediaire.GetSequenceNamed(old_sequence);
		              obj.setSequence(str); 
		              
		              String w = "123";
		              
		            });
		    	}
	    	}
	    	 else 
		     {
		    	  String message = String.format("ERROR: Plan level cannot be changed !.", NODE_MAXIMUM_LEVELS);
		          JOptionPane.showMessageDialog(tree, message, "Edit node", JOptionPane.ERROR_MESSAGE);
		      }
	    });
	    
	  }

	  @Override 
	  public void show(Component c, int x, int y) 
	  {
	    if (c instanceof JTree) 
	    {
	    	JTree tree = (JTree) c;
	    	path = tree.getPathForLocation(x, y);
	    	Optional.ofNullable(path).ifPresent(tp -> super.show(c, x, y));
	    }
	  }

}


/**********************************************************************************/
// http://www.java2s.com/Tutorials/Java/Swing_How_to/JTree/Refresh_new_JTree_model.htm
class MyTreeModelPlan extends DefaultTreeModel 
{

	  DefaultMutableTreeNode root = null;  // declaration en debut de fichier

	  public MyTreeModelPlan() 
	  {
		  super(new DefaultMutableTreeNode("Plan"));
		  root = (DefaultMutableTreeNode) getRoot();
	  }

	  public void load(boolean flag_load, ArrayList<String> datas, Class_plan intermediaire ) 
	  {
		  root.removeAllChildren();
		  
		  if (flag_load)
		  {	
			  
			  DefaultMutableTreeNode treeObj = null;
			
			  for(int i = 0 ; i < datas.size() ; i++)
			  {
				  boolean retval = datas.get(i).contains("-");
				  if(retval == false )
				  {
					  treeObj = new DefaultMutableTreeNode( datas.get(i) );
					  root.add(treeObj);
					  intermediaire.addSequence(new TestPlan("test", 1, datas.get(i), "", "") );
				  }
				  else
				  {
					  String[] parts = datas.get(i).split("-");
					  treeObj.add(new DefaultMutableTreeNode( parts[0] ));
					  intermediaire.addSequence(new TestPlan("subtest", 1, parts[0], parts[1], parts[2]) );
				  }
			  }
			  
		/*	  
			   category = new DefaultMutableTreeNode("xxxxxxxxxx");
			    root.add(category);
				 
			    category.add(new DefaultMutableTreeNode("bli"));
		  		category.add(new DefaultMutableTreeNode("zorbi")); 
				 
			    category = new DefaultMutableTreeNode("yyyyyyyyyyyyyyyyyyyyyyy");
			    root.add(category);
				 
			    category.add(new DefaultMutableTreeNode("Tim Lindholm"));
		  		category.add(new DefaultMutableTreeNode("Frank Yellin")); 
			*/  
			/*  
			  values = new String[] { "A", "A1", "A2", "B", "B1", "B2" };
			  DefaultMutableTreeNode childNode = new DefaultMutableTreeNode(values[0]);
			  DefaultMutableTreeNode leafNode = new DefaultMutableTreeNode(values[1]);
			  childNode.add(leafNode);
			  leafNode = new DefaultMutableTreeNode(values[2]);
			  childNode.add(leafNode);

			  root.add(childNode);

			  childNode = new DefaultMutableTreeNode(values[3]);
			  leafNode = new DefaultMutableTreeNode(values[4]);
			  childNode.add(leafNode);
			  leafNode = new DefaultMutableTreeNode(values[5]);
			  childNode.add(leafNode);
			  root.add(childNode);
*/
			  nodeStructureChanged(root);
			
		  }
	  }

	  public TreeNode getRootNode() 
	  {
		  return root;
	  }
	}



//// Traversing Trees

// Set the selected Jtree Node to JTable


/*
public void printDescendants(TreeNode root) {
	  System.out.println(root);
	  Enumeration children = root.children();
	  if (children != null) {
	    while(children.hasMoreElements()) {
	      printDescendants((TreeNode)children.nextElement());
	    }
	  }
	}*/


/*
start at root
If is a leaf - Print node name and return
Print --- node name ----
If node has children - recurse with each child (starting at 2)
Print +++ Node name ++++


public static void print(DefaultMutableTreeNode aNode)
{
    String name = aNode.toString();
    int level= aNode.getLevel();
    String placement = "";
    while (level > 0)
    {
        placement += ">";
        level--;
    }
    if(aNode.isLeaf())
    {
        System.out.println(placement + name);
        return;
    }

    System.out.println(placement + "--- " + name + " ---");
    for(int i = 0 ; i < aNode.getChildCount() ; i++)
    {
        print((DefaultMutableTreeNode)aNode.getChildAt(i));
    }
    System.out.println(placement + "+++ " + name + " +++");
}
*/



// https://www.journaldev.com/1112/how-to-write-xml-file-in-java-dom-parser


//    https://stackoverflow.com/questions/22005632/converting-jtree-to-xml-in-java



/*

public String getNodeIndex(JTree tree, TreeNode node) {
    TreeNode root = (TreeNode) tree.getModel().getRoot();
    if (node == root) {
        return "";
    }
    TreeNode parent = node.getParent();
    if (parent == null) {
        return null;
    }
    String parentIndex= getNodeIndex(tree, parent);
    if (parentIndex == null) {
        return null;
    }
    return parentIndex+"."+parent.getIndex(node);
}

*/




/*
Get the root of the tree:

	 tree.getModel().getRoot();
	then get the number of children of this root node:

	 tree.getModel().getChildCount(rootNode)
	then go from 0 to the number of children and call

	tree.getModel().getChild(rootNode, i)

*/



// https://stackoverflow.com/questions/22005632/converting-jtree-to-xml-in-java



/*

DefaultMutableTreeNode top = new DefaultMutableTreeNode("The Java Series");
DefaultMutableTreeNode category;
DefaultMutableTreeNode book;

category = new DefaultMutableTreeNode("Books for Java Programmers");
top.add(category);

//Tutorial
book = new DefaultMutableTreeNode("The Java Tutorial: Object-Oriented Programming for the Internet");
    book.add(new DefaultMutableTreeNode("Mary Campione"));
    book.add(new DefaultMutableTreeNode("Kathy Walrath"));
category.add(book);

//Arnold/Gosling
book = new DefaultMutableTreeNode("The Java Programming Language");
    book.add(new DefaultMutableTreeNode("Ken Arnold"));
    book.add(new DefaultMutableTreeNode("James Gosling"));
category.add(book);

//FAQ
book = new DefaultMutableTreeNode("The Java FAQ");
    book.add(new DefaultMutableTreeNode("Jonni Kanerva"));
category.add(book);

//Chan/Lee
book = new DefaultMutableTreeNode("The Java Class Libraries: An Annotated Reference");
    book.add(new DefaultMutableTreeNode("Patrick Chan"));
    book.add(new DefaultMutableTreeNode("Rosanna Lee"));
category.add(book);

//Threads
book = new DefaultMutableTreeNode("Concurrent Programming in Java: Design Principles and Patterns");
    book.add(new DefaultMutableTreeNode("Doug Lea"));
category.add(book);

category = new DefaultMutableTreeNode("Books for Java Implementers");
top.add(category);

//VM
book = new DefaultMutableTreeNode("The Java Virtual Machine Specification");
    book.add(new DefaultMutableTreeNode("Tim Lindholm"));
    book.add(new DefaultMutableTreeNode("Frank Yellin"));
category.add(book);

//Language Spec
book = new DefaultMutableTreeNode("The Java Language Specification");
    book.add(new DefaultMutableTreeNode("James Gosling"));
    book.add(new DefaultMutableTreeNode("Bill Joy"));
    book.add(new DefaultMutableTreeNode("Guy Steele"));
category.add(book);


*/