import java.lang.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.tree.*;
import java.util.*;

public class MoveTree extends JTree // JPanel ?
{
    ComradesNode ROOT, NOW;
    JPanel PANEL;
    BoardPosition BP, START;
    String START_FEN;
    int SPACE = 5; // prefer
    boolean WTM, FOCUS;
    int MOVE_NUMBER;
    int v = 0;
    boolean JUMP = false;

    public MoveTree (BoardPosition bp, ComradesNode root, JPanel panel)
    {
	super (new DefaultTreeModel (root));
	ROOT = root;
	BP = bp;
	START = new BoardPosition (BP); // copy
	START_FEN = new String (BP.GetFEN ());
	PANEL = panel; // copy
	PANEL.removeAll ();
	PANEL.setLayout (null); // absolute
	NOW = ROOT;
	WTM = BP.WTM;
	MOVE_NUMBER = BP.MOVE_NUMBER;
	FOCUS = false;
    }

    public void JumpToNode (ComradesNode N)
    {
	ComradesNode T = N;
	BP.CF.HaltInstances ();
	JUMP = true;
	while (T.MainLineParent != null)
	    {
		T.MainLineParent.MainLineNode = T;
		T.MainLineParent.mainline = T.mv; // valid ?
		T = T.MainLineParent;
	    }
	BP.SetFEN (new StringTokenizer (START_FEN));
	NOW = ROOT;
	while (N != NOW) // attend
	    BP.MakeMove32 (NOW.mainline.move, NOW.mainline.fancy);
	BP.MakeNormal ();
	BP.CF.redraw ();
	BP.CF.BoardPositionChanged (); // ensure
	PaintPanel ();
	BP.CF.EquipInstances ();
	JUMP = false;
    }

    public void NodeMove (int mv, String S)
    {
        int i, n = NOW.getChildCount ();
        ComradesNode PREV = NOW;
        PREV.mainline = new TypeMove (mv, S);
        for (i = 0; i < n; i++)
            {
                if (PREV.getChildAt (i).mv.move == mv)
                    {
                        NOW = PREV.getChildAt (i);
                        break;
                    }
            }
        if (i >= n)
            NOW = new ComradesNode (PREV, PREV.mainline);
        PREV.MainLineNode = NOW;
        NOW.MainLineParent = PREV;
	FOCUS = true;
	if (!JUMP)
	    PaintPanel ();
    }

    public void NodeExpansion (int LEFT, ComradesNode N, int ht)
    {
	int h = LEFT;
	ComradesLabel C;
	Dimension D;
	C = new ComradesLabel (N, this, false, ht);
	D = C.getPreferredSize ();
	C.setBounds (h, v, D.width, D.height);
	h += D.width + SPACE;
	PANEL.add (C);
	ht++;

	while (N.getChildCount () > 0)
	    {
		ComradesNode F = N.MainLineNode;
		C = new ComradesLabel (F, this, false, (ht % 2 == 0 || N == ROOT) ? ht : 0);
		if (F == NOW) // HACK // valid ?
		    C.setBackground (Color.orange); // partial ?
		D = C.getPreferredSize ();
		if (h + D.width > 360)
		    {
			h = LEFT; // LIMIT
			v += 15;
		    }
		C.setBounds (h, v, D.width, D.height);
		h += D.width + SPACE;
		PANEL.add (C);
		if (N.is_expanded)
		    {
			C = new ComradesLabel (N, this, true, 0);
			D = C.getPreferredSize ();
			C.setBounds (h, v, D.width, D.height);
			PANEL.add (C);
			int n = N.getChildCount ();
			for (int i = 0; i < n; i++)
			    {
				v += 15;
				NodeExpansion (LEFT + 10, N.getChildAt (i), ht);
			    }
			break;
		    }
		N = F.transpose; // HACK
		ht++;
	    }
    }

    public void PaintPanel () // manual
    {
	v = 0; // attend
	PANEL.removeAll (); // HACK
	NodeExpansion (0, ROOT, (WTM ? 0 : 1) + 2 * MOVE_NUMBER - 1);
	PANEL.repaint ();
	if (FOCUS)
	    NOW.LABEL.requestFocus ();
    }

}
