import java.awt.*;
import javax.swing.*;
import java.awt.event.*;

public class BridgesApplet extends JApplet implements MouseListener, ActionListener
{
    Point selectedIsland   = new Point(-1, -1);
    Board board            = null;
    Board undoBoard        = null;
    boolean rightClick;
    Button newGameBtn      = new Button("New Game");
    Button showSolutionBtn = new Button("Show Solution");
    boolean showSolution   = false;
    Choice boardSize       = new Choice();
    int islandDiameter     = 25;
    Font font              = null;

    public void newGame()
    {
        this.showSolution = false;
        showSolutionBtn.setLabel("Show Solution");
        if (boardSize.getSelectedItem().equals("5 x 5"))
        {
            board          = new Board(5, 5);
            islandDiameter = 100;
            font           = new Font("Arial", Font.PLAIN, 24);
        }
        else if (boardSize.getSelectedItem().equals("10 x 10"))
        {
            board          = new Board(10, 10);
            islandDiameter = 50;
            font           = new Font("Arial", Font.PLAIN, 22);
        }
        else if (boardSize.getSelectedItem().equals("15 x 10"))
        {
            board          = new Board(15, 10);
            islandDiameter = 33;
            font           = new Font("Arial", Font.PLAIN, 16);
        }
        else if (boardSize.getSelectedItem().equals("15 x 15"))
        {
            board          = new Board(15, 15);
            islandDiameter = 33;
            font           = new Font("Arial", Font.PLAIN, 14);
        }
        else if (boardSize.getSelectedItem().equals("20 x 20"))
        {
            board          = new Board(20, 20);
            islandDiameter = 25;
            font           = new Font("Arial", Font.PLAIN, 12);
        }
        else if (boardSize.getSelectedItem().equals("30 x 30"))
        {
            board          = new Board(30, 30);
            islandDiameter = 16;
            font           = new Font("Arial", Font.PLAIN, 10);
        }
    }

    public void actionPerformed(ActionEvent e)
    {
        if(e.getActionCommand().equals("New Game"))
        {
            newGame();
            repaint();
        }
        else if(e.getActionCommand().equals("Show Solution"))
        {
            this.showSolution = true;
            showSolutionBtn.setLabel("Hide Solution");
            repaint();
        }
        else if(e.getActionCommand().equals("Hide Solution"))
        {
            this.showSolution = false;
            showSolutionBtn.setLabel("Show Solution");
            repaint();
        }
    }

    public void init()
    {
        // this is a workaround for a security conflict with some browsers
        // including some versions of Netscape & Internet Explorer which do
        // not allow access to the AWT system event queue which JApplets do
        // on startup to check access. May not be necessary with your browser.
        JRootPane rootPane = this.getRootPane();    
        rootPane.putClientProperty("defeatSystemEventQueueCheck", Boolean.TRUE);
           
        // create buttons
        this.setLayout(new BorderLayout());
        Panel p = new Panel();
        p.setLayout(new FlowLayout());
        this.add(p, BorderLayout.PAGE_END);
        newGameBtn.setPreferredSize(new Dimension(150, 50));
        p.add(newGameBtn);
        newGameBtn.addActionListener(this);
        showSolutionBtn.setPreferredSize(new Dimension(150, 50));
        p.add(showSolutionBtn);
        showSolutionBtn.addActionListener(this);

        p.add(new Label("Board Size"));
        boardSize.add("5 x 5");
        boardSize.add("10 x 10");
        boardSize.add("15 x 10");
        boardSize.add("15 x 15");
        boardSize.add("20 x 20");
        boardSize.add("30 x 30");
        boardSize.select("20 x 20");
        p.add(boardSize);

        // provide any initialisation necessary for your JApplet
        addMouseListener(this);
        newGame();
    }

    public void start()
    {
    }


    public void stop()
    {
    }

    public void mouseEntered (MouseEvent me){} 
    public void mousePressed (MouseEvent me)
    {
        if(showSolution)
        {
            return;
        }

        int x = me.getX() / islandDiameter, y = me.getY() / islandDiameter;
        if(this.board.islandExistsAtSquare(x, y))
        {
            this.selectedIsland.x = x;
            this.selectedIsland.y = y;
            this.rightClick = me.getButton() != MouseEvent.BUTTON1;
        }
        else
        {
            this.selectedIsland.x = -1;
        }
        repaint();
    } 
    public void mouseReleased (MouseEvent me)
    {
        int x = me.getX() / islandDiameter, y = me.getY() / islandDiameter;
        if(this.board.islandExistsAtSquare(x, y))
        {
            if(this.rightClick)
            {
                this.board.removeBridge(selectedIsland.x, selectedIsland.y, x, y);
            }
            else
            {
                this.board.addBridge(selectedIsland.x, selectedIsland.y, x, y);
                if(this.board.isSolved())
                {
                    repaint();
                    JOptionPane.showMessageDialog(null, "Well done!");
                }
            }
        }
        this.selectedIsland.x = -1;
        repaint();
    }  
    public void mouseExited (MouseEvent me) {}
    public void mouseClicked (MouseEvent me){}

    public void paint(Graphics g)
    {
        // Erase previous frame
        g.setColor(Color.WHITE);
        g.fillRect(0, 0, 501, 501);

        drawBoard(g);
        //JOptionPane.showMessageDialog(null, "" + selectedIsland.x + ", " + selectedIsland.y);
    }

    public void drawBoard(Graphics g)
    {
        g.setFont(font);
        for(int i = 0; i < this.board.getWidth(); i++)
        {
            for(int j = 0; j < this.board.getHeight(); j++)
            {
                int n = board.getNumRequiredBridges(i, j);
                if(n > 0)
                {
                    if(i == selectedIsland.x && j == selectedIsland.y)
                    {
                        g.setColor(this.rightClick ? Color.RED : Color.GREEN);
                        g.fillOval((i * islandDiameter), (j * islandDiameter), islandDiameter, islandDiameter);
                    }
                    else
                    {
                        g.setColor(showSolution || n == board.getCurrentNumBridges(i, j) ? new Color(252, 207, 124) : new Color(192, 192, 192));
                        g.drawOval((i * islandDiameter), (j * islandDiameter), islandDiameter, islandDiameter);
                    }
                    g.setColor(showSolution || n == board.getCurrentNumBridges(i, j) ? new Color(252, 207, 124) : Color.BLACK);
                    g.drawString("" + n, (i * islandDiameter) + (int)(islandDiameter / 2.5), (j * islandDiameter) + (int)(islandDiameter * 0.68));
                    g.setColor(Color.BLACK);

                    int s = this.board.getNumSouthBridges(i, j, this.showSolution);
                    if(s > 0)
                    {
                        int islandDueSouthY = this.board.getDueSouthIsland(i, j);
                        if(islandDueSouthY != -1)
                        {
                            if(s == 1)
                            {
                                g.drawLine((i * islandDiameter) + (int)(islandDiameter / 2), (j * islandDiameter) + islandDiameter, (i * islandDiameter) + (islandDiameter / 2), (islandDueSouthY * islandDiameter));
                            }
                            else if(s == 2)
                            {
                                g.drawLine((i * islandDiameter) + (int)(islandDiameter / 4), (j * islandDiameter) + islandDiameter, (i * islandDiameter) + (int)(islandDiameter / 4), (islandDueSouthY * islandDiameter));
                                g.drawLine((i * islandDiameter) + (int)(islandDiameter * 0.6), (j * islandDiameter) + islandDiameter, (i * islandDiameter) + (int)(islandDiameter * 0.6), (islandDueSouthY * islandDiameter));
                            }
                        }
                    }
                    int e = this.board.getNumEastBridges(i, j, this.showSolution);
                    if(e > 0)
                    {
                        int islandDueEastX = this.board.getDueEastIsland(i, j);
                        if(islandDueEastX != -1)
                        {
                            if(e == 1)
                            {
                                g.drawLine((i * islandDiameter) + islandDiameter, (j * islandDiameter) + (int)(islandDiameter / 2), (islandDueEastX * islandDiameter), (j * islandDiameter) + (int)(islandDiameter / 2));
                            }
                            else if(e == 2)
                            {
                                g.drawLine((i * islandDiameter) + islandDiameter, (j * islandDiameter) + (int)(islandDiameter / 4), (islandDueEastX * islandDiameter), (j * islandDiameter) + (int)(islandDiameter / 4));
                                g.drawLine((i * islandDiameter) + islandDiameter, (j * islandDiameter) + (int)(islandDiameter / 2), (islandDueEastX * islandDiameter), (j * islandDiameter) + (int)(islandDiameter / 2));
                            }
                        }
                    }
                }
            }
        }
    }
}
