import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.Random;

import javax.swing.JButton;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.Timer;

import breadboards.*;


public class GUIFun extends Breadboard {
    
    Random random = new Random();
    GLabel gLabel;
    JTextArea textArea;
    JTextField textField;
    JButton button1;
    JButton button2;
    JButton button3;
    Timer timer;
    
    Button1ActionListener button1ActionListener;
    
    public static void main(String[] args) {
      new GUIFun();
    }
    
    public GUIFun() {
      this.getPanel(this.NORTH).remove(this.getTextArea());
      
      this.getPanel(this.SOUTH).remove(this.getLabel());
      this.getPanel(this.SOUTH).remove(this.getTextField());
      this.getPanel(this.SOUTH).remove(this.getButton2());
      this.getPanel(this.SOUTH).remove(this.getButton1());
    }
    
    public Color randomColor() {
        return new Color(random.nextInt(256),random.nextInt(256), random.nextInt(256));
    }
    
    public void init() {

        this.setSize(500,500);
        
        // ADD LABELS, TEXT AREAS, AND TEXT FIELDS TO CANVAS AND/OR WINDOW...
        
        this.gLabel = new GLabel("I'm a GLabel");
        gLabel.setFont("TimesNewRoman"); 
        gLabel.setFontSize(20);
        // use fontname-style-size, with style = PLAIN, BOLD, BOLDITALIC, ITALIC
        
        this.add(gLabel,100,300);
        
        this.textArea = new JTextArea(4,35);
        this.textArea.setText("I'm a text area");
        this.textArea.setLineWrap(true);
        this.textArea.setWrapStyleWord(true);
        this.getPanel(NORTH).add(textArea);
        
        this.textField = new JTextField("I'm a text field");
        this.getPanel(SOUTH).add(textField);
        
        // ADD BUTTONS THAT DO SOMETHING IN THREE WAYS...
        
        // button 1 should log something to the console..
        this.button1 = new JButton("btn 1");                     
        button1ActionListener = new Button1ActionListener();    // <-- Button1ActionListener has a hard time modifying this class
        this.button1.addActionListener(button1ActionListener);
        this.getPanel(SOUTH).add(button1);
        
        // button 2 should log something to the console and change the canvas background color..
        this.button2 = new JButton("btn 2");
        Button2ActionListener button2ActionListener = new Button2ActionListener();   // <-- setup and intended action are separated
        this.button2.addActionListener(button2ActionListener);
        this.getPanel(SOUTH).add(button2);
        
        // button 3 should log something to the console and change the north background
        this.button3 = new JButton("btn 3");                    // <-- Often the best option...
        this.button3.addActionListener(new ActionListener() {   // <-- Anonymous inner class (note, ActionListener is an interface name)
            public void actionPerformed(ActionEvent e) {
                System.out.println("Button 3 was clicked!");
                GUIFun.this.getPanel(NORTH).setBackground(GUIFun.this.randomColor());
            }});
        this.getPanel(SOUTH).add(button3);
        
        // ADD A MOUSE LISTENER TO THE CANVAS TO DETECT WHERE MOUSE CLICKS OCCUR AND IF MOUSE CLICKED INSIDE Rect1...
        // AND TO TAKE SOME ACTION ON "THIS" (MOVE CLICKED RECTS A BIT)
        
        GRect rect1 = new GRect(230,20,100,100);
        rect1.setFilled(true);
        rect1.setFillColor(Color.WHITE);
        this.add(rect1);
        
        this.getPanel(CENTER).addMouseListener(new MouseListener() {

            // on mouse click, report coordinates to console
            // and check if rect1 was clicked, reporting this to console too
            public void mouseClicked(MouseEvent e) {
                System.out.println("Mouse click! (" + e.getX() + ", " + e.getY() + ")");
                if (rect1.contains(e.getX(),e.getY())) {
                    System.out.println("rect 1 was clicked!");
                }
            }

            // if mouse pressed on any GRect, move it down and to the right 1 pixel
            public void mousePressed(MouseEvent e) {
                GObject element = GUIFun.this.getElementAt(e.getX(), e.getY());
                if (element instanceof GRect) {
                    ((GRect) element).move(1, 1);
                }
            }

            public void mouseReleased(MouseEvent e) {}
            public void mouseEntered(MouseEvent e) {}
            public void mouseExited(MouseEvent e) {}
            });
        
        // OPTIONALLY, YOU CAN ADD THE LISTENERS DIRECTLY TO COMPONENTS LIKE Rect2...
        
        GRect rect2 = new GRect(230,200,100,100);
        rect2.setFilled(true);
        rect2.setFillColor(Color.WHITE);
        
        rect2.addMouseListener(new MouseListener() {
            public void mouseClicked(MouseEvent e) {
                System.out.println("rect 2 was clicked!");   
            }

            public void mousePressed(MouseEvent e) {}
            public void mouseReleased(MouseEvent e) {}
            public void mouseEntered(MouseEvent e) {}
            public void mouseExited(MouseEvent e) {}
            });
        this.add(rect2);
        
        // MOUSE MOTION IS DIFFERENT THAN MOUSE CLICKING & PRESSING...
        
        this.getPanel(CENTER).addMouseMotionListener(new MouseMotionListener() {
           
            public void mouseDragged(MouseEvent e) {}   // <-- we'll do this in a bit...

            // let textArea report constantly the position of the mouse (update with every move)
            public void mouseMoved(MouseEvent e) {
                GUIFun.this.textArea.setText("mouse now at: (" + e.getX() + ", " + e.getY() + ")");
            }});

        
        // Adding a key listener... 
        this.addKeyListener(new KeyListener() {

            public void keyTyped(KeyEvent e) {
                System.out.println(e.getKeyChar());
            }

            public void keyPressed(KeyEvent e) {
                System.out.println(e.getKeyCode());
                switch (e.getKeyCode()) {
                case 37 : System.out.println("left arrow"); break;
                case 38 : System.out.println("up arrow"); break;
                case 39 : System.out.println("right arrow"); break;
                case 40 : System.out.println("down arrow"); break;
                }
            }
            
            public void keyReleased(KeyEvent e) {}
        });
        
        this.setFocusable(true);
        this.requestFocusInWindow();        // <-- don't forget this -- otherwise your keystrokes won't be 
                                            //     processed by the listeners attached to the canvas!
                                            //     (look in the api - addKeyListeners() adds them to the canvas)
 
        
        // ADDING YOUR OWN TIMER (Instead of breadboard's built-in timer)
        // And using it to process elements currently on the canvas (named or not)...
        
        GOval oval = new GOval(50,50,50,50);
        oval.setFilled(true);
        oval.setFillColor(Color.RED);
        this.add(oval);
        
        GRect littleRect = new GRect(25,25,25,25);
        littleRect.setFilled(true);
        littleRect.setFillColor(Color.RED);
        this.add(littleRect);
        
        int delay = 1000;
        timer = new Timer(delay, new ActionListener() {

            public void actionPerformed(ActionEvent e) {  // cycle through elements on canvas, 
                                                          // make SOUTH region and all RECTS the same random color
                Color color = GUIFun.this.randomColor();
                GUIFun.this.getPanel(SOUTH).setBackground(color);
                int numElements = GUIFun.this.getElementCount();
                for (int i = 0; i < numElements; i++) {
                    GObject element = GUIFun.this.getElement(i);
                    if (element instanceof GRect) {
                        ((GRect) element).setFillColor(color);
                    }
                }
                
            }});
        timer.start();
    }
    
    public class Button2ActionListener implements ActionListener {  // <-- Inner class
        
        public void actionPerformed(ActionEvent e) {
            System.out.println("Button 2 was clicked!");
            GUIFun.this.setBackground(GUIFun.this.randomColor());
        }
    }

    public void run() {
        
    }
    
}

