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.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.ButtonModel;
import javax.swing.DefaultCellEditor;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JColorChooser;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.border.EmptyBorder;
import javax.swing.JLabel;
import javax.swing.JOptionPane;

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.io.BufferedInputStream;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;

import javax.swing.JTextArea;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingConstants;
import javax.swing.WindowConstants;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.JSeparator;
import javax.swing.JTable;

import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.imageio.ImageIO;
import javax.swing.AbstractButton;
import javax.swing.ButtonGroup;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JRadioButton;


import javax.swing.border.*;
import javax.swing.event.*;
import javax.swing.table.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import java.awt.*;

import java.awt.*;
import java.beans.DefaultPersistenceDelegate;
import java.beans.XMLDecoder;
import java.beans.XMLEncoder;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.Reader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Objects;
import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeModel;

// MVC   modelisation  visualization  command

public class jdialog01 extends JDialog 
{
	
	private static JTable table;
	
	private JTree tree;
	
	private static DefaultTableModel xxxmodel;
	
	private boolean close_Jdialog = false;
	
	
	private JButton btn_save_tree;
	private JButton btn_load_tree;
	
	public jdialog01(JFrame f, boolean modal) 
	{
       super(f, modal);

       // fermer la fenetre
       addWindowListener(new java.awt.event.WindowAdapter() 
       {
           public void windowClosing(java.awt.event.WindowEvent e) 
           {
        	   dispose();
           }
       });
       
       init();
     
	}

	// envoi les datas
	public void initialise( Object [] o)
	{
		
	}
 
	// retourne les datas
	public Object [] getDonnees()
	{
		return null;
	
	}
  
	private void init()
	{
	  	setResizable( false );
		setBounds(100, 100, 926, 550);
		setTitle("Properties");
		getContentPane().setLayout(null);
     	
		ImageIcon icon = null;
		icon = createImageIcon("resources/settings.png", "");
		setIconImage( icon.getImage() );
		
		setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
		setTitle("Settings state parameters ");
		
	
		
	
		
		JScrollPane scrollPane_2 = new JScrollPane();
		scrollPane_2.setBounds(50, 39, 183, 194);
		getContentPane().add(scrollPane_2);
		
		tree = new JTree();
		scrollPane_2.setViewportView(tree);
		
		 tree.setComponentPopupMenu(new TreePopupMenu());
		
		 
		 tree.addMouseListener(new MouseAdapter() {
		      public void mouseClicked(MouseEvent me) {
		        doMouseClicked(me);
		      }
		    });
		
		JScrollPane scrollPane = new JScrollPane();
		scrollPane.setBounds(294, 39, 532, 159);
		getContentPane().add(scrollPane);
		
		table = new JTable();
		table.setModel(new DefaultTableModel(
			new Object[][] {
				{null, null, null},
				{null, null, null},
				{null, null, null},
				{null, null, null},
				{null, null, null},
			},
			new String[] {
				"New column", "New column", "New column"
			}
		));
		scrollPane.setViewportView(table);

		//DefaultTableModel xxxmodel = new DefaultTableModel();
		 //DefaultTableModel xxxmodel = (DefaultTableModel) table.getModel();

		/*******************/
		
		btn_load_tree  = new JButton("Load");
		btn_load_tree.addActionListener(new ActionListener() 
		{
			public void actionPerformed(ActionEvent arg0) 
			{
				System.out.println("Btn load  \n");
			}
		});
		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");
/*				
				try (XMLDecoder xd = new XMLDecoder(new BufferedInputStream(new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8))))) 
				{
			        DefaultTreeModel m = (DefaultTreeModel) xd.readObject();
			        m.addTreeModelListener(new CheckBoxStatusUpdateListener());
			        tree.setModel(m);
			      }
*/
				
				try {
			        File file = File.createTempFile("output", ".xml");
			        // try (XMLEncoder xe = new XMLEncoder(new BufferedOutputStream(new FileOutputStream(file)))) {
			        try (XMLEncoder xe = new XMLEncoder(new BufferedOutputStream(Files.newOutputStream(file.toPath())))) {
			          xe.setPersistenceDelegate(CheckBoxNode.class, new DefaultPersistenceDelegate(new String[] {"label", "status"}));
			          xe.writeObject(tree.getModel());
			        }
			        // try (Reader r = new BufferedReader(new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8))) {
			        try (Reader r = Files.newBufferedReader(file.toPath(), StandardCharsets.UTF_8)) {
			          textArea.read(r, "temp");
			        }
			      } catch (IOException ex) {
			        ex.printStackTrace();
			      }
				
			}
		});
		btn_save_tree.setBounds(161, 257, 89, 23);
		getContentPane().add(btn_save_tree);
		
		/*******************/
		
		
		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);
		
		/*******************/
	}
	
	
    
	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;
		}
	}
	
	
	
	
	/******************************************/
	
	 void doMouseClicked(MouseEvent me) 
	 {
		    TreePath tp = tree.getPathForLocation(me.getX(), me.getY());
		 //   if (tp != null)
		 //     jtf.setText(tp.toString());
		 //   else
		 //     jtf.setText("");
		 System.out.println(tp);   
		    
		  }
	
  
}

class TreePopupMenu extends JPopupMenu 
{
	  protected TreePath path;
	  
	  private final Action addNodeAction = new AbstractAction("add") 
	  {
	    @Override public void actionPerformed(ActionEvent e) 
	    {
	    	JTree tree = (JTree) getInvoker();
	    	DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
	    	DefaultMutableTreeNode parent = (DefaultMutableTreeNode) path.getLastPathComponent();
	    	DefaultMutableTreeNode child = new DefaultMutableTreeNode("New node");
	    	model.insertNodeInto(child, parent, parent.getChildCount());
	    	tree.scrollPathToVisible(new TreePath(child.getPath())); // https://ateraimemo.com/Swing/ScrollRectToVisible.html

	    	// ajouter dans la table
	    	// DefaultTableModel xxxmodel = (DefaultTableModel) table.getModel();
	    	
	    	
	   	// DefaultTableModel xxxmodel = (DefaultTableModel) table.getModel();
	    	
	     //    xxxmodel.addRow(new Object[]{"Column 1", "Column 2", "Column 3"});
	    
	    }
	  };
	  
	  private final Action addReloadAction = new AbstractAction("add & reload") 
	  {
	    @Override public void actionPerformed(ActionEvent e) 
	    {
	      JTree tree = (JTree) getInvoker();
	      DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
	      DefaultMutableTreeNode parent = (DefaultMutableTreeNode) path.getLastPathComponent();
	      DefaultMutableTreeNode child = new DefaultMutableTreeNode("New node");
	      parent.add(child);
	      model.reload(parent); // = model.nodeStructureChanged(parent);
	      tree.scrollPathToVisible(new TreePath(child.getPath()));
	    }
	  };
	  
	  private final Action editNodeAction = new AbstractAction("edit") 
	  {
	    protected final JTextField textField = new JTextField(24) 
	    {
	      protected transient AncestorListener listener;
	      
	      @Override public void updateUI() 
	      {
	        removeAncestorListener(listener);
	        super.updateUI();
	        
	        listener = new AncestorListener() 
	        {
	          @Override public void ancestorAdded(AncestorEvent e) 
	          {
	            requestFocusInWindow();
	          }

	          @Override public void ancestorMoved(AncestorEvent e) { /* not needed */ }

	          @Override public void ancestorRemoved(AncestorEvent e) { /* not needed */ }
	        };
	        addAncestorListener(listener);
	      }
	    };
	    
	    @Override public void actionPerformed(ActionEvent e) 
	    {
	      Object node = path.getLastPathComponent();
	      if (!(node instanceof DefaultMutableTreeNode)) 
	      {
	        return;
	      }
	      
	      DefaultMutableTreeNode leaf = (DefaultMutableTreeNode) node;
	      textField.setText(leaf.getUserObject().toString());
	      JTree tree = (JTree) getInvoker();
	      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();
	              model.valueForPathChanged(path, str);
	              // leaf.setUserObject(str);
	              // model.nodeChanged(leaf);
	            });
	      }
	    }
	  };
	  
	  private final Action removeNodeAction = new AbstractAction("remove") 
	  {
	    @Override public void actionPerformed(ActionEvent e) {
	      DefaultMutableTreeNode node = (DefaultMutableTreeNode) path.getLastPathComponent();
	      if (!node.isRoot()) {
	        JTree tree = (JTree) getInvoker();
	        DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
	        model.removeNodeFromParent(node);
	      }
	    }
	  };

	  protected TreePopupMenu() {
	    super();
	    add(addNodeAction);
	    add(addReloadAction);
	    add(editNodeAction);
	    addSeparator();
	    add(removeNodeAction);
	  }

	  @Override public void show(Component c, int x, int y) 
	  {
	    if (c instanceof JTree) {
	      JTree tree = (JTree) c;
	      // TreePath[] tsp = tree.getSelectionPaths();
	      path = tree.getPathForLocation(x, y);
	      // if (Objects.nonNull(path) && Arrays.asList(tsp).contains(path)) {
	      Optional.ofNullable(path).ifPresent(p -> {
	        tree.setSelectionPath(p);
	        super.show(c, x, y);
	      });
	    }
	  }
}