package arbitrary;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Hashtable;

import javax.swing.BorderFactory;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.JToggleButton;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;

public class Sudoku extends JFrame
{

    /**
     * 
     */
    private static final long serialVersionUID = 7833936210681698390L;

    public class Square extends JPanel
    {
        /**
         * 
         */
        private static final long serialVersionUID = -4599448844538694669L;

        private Hashtable<Integer, Boolean> table = new Hashtable<Integer, Boolean>();

        private PuzzleSquare puzzleSquare;

        public Square()
        {
            //setPreferredSize( new Dimension(100,100) );
//			this.setLayout( new GridLayout(3,3) );
            for (int i = 1; i <= 9; i++)
            {
                table.put(i, true);
                JToggleButton cbox = new JToggleButton(Integer.toString(i),
                        true);
                cbox.setMargin(new Insets(0, 0, 0, 0));
                cbox.setForeground(Color.DARK_GRAY);
                cbox.setFont(cbox.getFont().deriveFont(10.0f));
//				cbox.setFont( cbox.getFont().deriveFont(Font.PLAIN) );
                cbox.addActionListener(new ActionListener()
                {
                    public void actionPerformed(ActionEvent e)
                    {
                        JToggleButton cbox = (JToggleButton) e.getSource();
                        int i = Integer.parseInt(cbox.getText());
                        mark(i, cbox.isSelected());
//						if (!cbox.isSelected())
//							cbox.setForeground(Color.BLACK);
//						else
//							cbox.setForeground(Color.LIGHT_GRAY);

                        int isolated = getIsolated();
                        Component[] comps = Square.this.getComponents();
                        for (Component comp : comps)
                        {
                            if (comp instanceof JToggleButton)
                            {
                                JToggleButton cbox1 = (JToggleButton) comp;
//								cbox1.setFont( cbox1.getFont().deriveFont(Font.PLAIN) );
                                int k = Integer.parseInt(cbox1.getText());
                                if (k == isolated)
                                {
//									cbox1.setForeground(Color.BLACK);
//									cbox1.setFont( cbox1.getFont().deriveFont(Font.BOLD) );
                                    puzzleSquare.field.setText(Integer
                                            .toString(k));
                                }
                            }

                        }
                        repaint();
                    }
                });
                this.add(cbox);
            }
        }

        public void isolate(int i)
        {
            Component[] comps = this.getComponents();
            for (int j = 1; j <= 9; j++)
            {
                if (i == j)
                {
                    table.put(j, true);
                }
                else
                {
                    table.put(j, false);
                }

                if (comps[j - 1] instanceof JToggleButton)
                {
                    JToggleButton cbox1 = (JToggleButton) comps[j - 1];
                    cbox1.setSelected(false);
//					cbox1.setFont( cbox1.getFont().deriveFont(Font.PLAIN) );
//					cbox1.setForeground(Color.LIGHT_GRAY);
                    int k = Integer.parseInt(cbox1.getText());
                    if (k == i)
                    {
                        cbox1.setSelected(true);
//						cbox1.setForeground(Color.BLACK);
//						cbox1.setFont( cbox1.getFont().deriveFont(Font.BOLD) );
                    }
                }
            }
        }

        public void setAllEnabled(boolean value)
        {
            Component[] comps = this.getComponents();
            for (int i = 0; i < 9; i++)
            {
                if (comps[i] instanceof JToggleButton)
                {
                    JToggleButton cbox1 = (JToggleButton) comps[i];
                    cbox1.setEnabled(value);
                }
            }
        }

        public void mark(int i, boolean value)
        {
            table.put(i, value);
        }

        public int getIsolated()
        {
            int total = 0;
            int value = 0;
            for (int j = 1; j <= 9; j++)
            {
                Boolean current = table.get(new Integer(j));
                if (current.booleanValue())
                {
                    total++;
                    value = j;
                }
            }

            if (total == 1)
            {
                return value;
            }
            else
            {
                return -1;
            }
        }

        public void setPuzzleSquare(PuzzleSquare ps)
        {
            puzzleSquare = ps;
        }
    }

    public class PuzzleSquare extends JPanel
    {
        /**
         * 
         */
        private static final long serialVersionUID = 1601269117981965229L;

        public JCheckBox editable;

        public JTextField field;

        private Square square;

        public PuzzleSquare(Square s)
        {
            this.square = s;
            editable = new JCheckBox();
            field = new JTextField(1);

            editable.setFont(editable.getFont().deriveFont(16.0f));

            this.add(editable);
            this.add(field);
            this.setBorder(BorderFactory.createLineBorder(Color.GRAY, 1));

            editable.addActionListener(new ActionListener()
            {
                public void actionPerformed(ActionEvent arg0)
                {
                    field.setEditable(!editable.isSelected());
                    if (editable.isSelected())
                    {
                        square.setAllEnabled(false);
                    }
                    else
                    {
                        square.setAllEnabled(true);
                    }
                }
            });
            field.addCaretListener(new CaretListener()
            {
                public void caretUpdate(CaretEvent e)
                {
                    try
                    {
                        int i = Integer.parseInt(field.getText());
                        square.isolate(i);
                    }
                    catch (NumberFormatException ex)
                    {
                    }
                }
            });
        }
    }

    private Square[][] squares = new Square[9][9];

    private PuzzleSquare[][] puzzleSquares = new PuzzleSquare[9][9];

    public Sudoku()
    {
        super("Sudoku Helper");

        JPanel contentPane = new JPanel();
        contentPane.setLayout(new BorderLayout());
        this.setContentPane(contentPane);

        JPanel mainPanel = new JPanel();
        mainPanel.setLayout(new GridLayout(3, 3));
        contentPane.add(mainPanel, BorderLayout.CENTER);

        JPanel puzzleContainer = new JPanel();
        JPanel puzzlePanel = new JPanel();
        puzzlePanel.setLayout(new GridLayout(3, 3));
        puzzleContainer.add(puzzlePanel);
        contentPane.add(puzzleContainer, BorderLayout.SOUTH);

        JPanel[][] quadrants = new JPanel[3][3];
        JPanel[][] puzzleQuadrants = new JPanel[3][3];
        for (int i = 0; i < 3; i++)
        {
            for (int j = 0; j < 3; j++)
            {
                quadrants[i][j] = new JPanel();
                quadrants[i][j].setLayout(new GridLayout(3, 3));
                quadrants[i][j].setBorder(BorderFactory
                        .createLineBorder(Color.BLACK));
                mainPanel.add(quadrants[i][j]);

                puzzleQuadrants[i][j] = new JPanel();
                puzzleQuadrants[i][j].setLayout(new GridLayout(3, 3));
                puzzleQuadrants[i][j].setBorder(BorderFactory
                        .createLineBorder(Color.BLACK));
                puzzlePanel.add(puzzleQuadrants[i][j]);
            }
        }

        for (int i = 0; i < 9; i++) // row
        {
            for (int j = 0; j < 9; j++) // column
            {
                squares[i][j] = new Square();
                squares[i][j].setBorder(BorderFactory
                        .createLineBorder(Color.GRAY));
                quadrants[i / 3][j / 3].add(squares[i][j]);

                puzzleSquares[i][j] = new PuzzleSquare(squares[i][j]);
                puzzleSquares[i][j].setBorder(BorderFactory
                        .createLineBorder(Color.GRAY));
                puzzleQuadrants[i / 3][j / 3].add(puzzleSquares[i][j]);

                squares[i][j].setPuzzleSquare(puzzleSquares[i][j]);
            }
        }

        this.pack();
    }

    /**
     * @param args
     */
    public static void main(String[] args)
    {
        Sudoku frame = new Sudoku();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }

}
