import acm.graphics.*;
import acm.program.*;
import java.util.*;
import java.awt.Font;
import java.awt.event.*;
import javax.swing.*;

/* This program allows the user to create a set of labels and then drag
 * them around in the window.
 */
public class WordCloud extends GraphicsProgram {
    /* Private constants */
    private static final int MAX_NAME = 25;

    /* Private fields */
    private HashMap<String,GLabel> contents;
    private JTextField nameField;
    private GLabel currentLabel;
    private GPoint last;

    public void init() {
        contents = new HashMap<String,GLabel>();
        addInteractors();
    }

    /* Creates the control strip at the bottom of the window */
    private void addInteractors() {
        add(new JLabel("Name"), SOUTH);
        nameField = new JTextField(MAX_NAME);
        add(nameField, SOUTH);

        add(new JButton("Add"), SOUTH);
        add(new JButton("Remove"), SOUTH);
        add(new JButton("Clear"), SOUTH);
        
        addActionListeners();
    }

    /* Adds a label with the given name at the center of the window */
    private void addLabel(String name) {
        GLabel label = new GLabel(name);
        label.setFont(new Font("Helvetica", Font.BOLD, 18));
        double labelX = getWidth() / 2.0 - label.getWidth() / 2.0;
        double labelY = getHeight() / 2 + label.getAscent() / 2.0;
        add(label, labelX, labelY);
        contents.put(name, label);
    }

    /* Removes all labels in the contents table */
    private void removeContents() {
        for (String labelName : contents.keySet()) {
            remove(contents.get(labelName));
        }
        
        contents.clear();       // Clear all entries in the hashmap
    }

    /* Called in response to button actions */
    public void actionPerformed(ActionEvent e) {
        String labelName = nameField.getText();

        // Detect both clicks and ENTER for adding a new label
        if (e.getActionCommand().equals("Add")) {
            addLabel(labelName);
        } else if (e.getActionCommand().equals("Remove")) {
            if (contents.containsKey(labelName)) {
                remove(contents.get(labelName));
            }
        } else if (e.getActionCommand().equals("Clear")) {
            removeContents();
        }
    }

    /* Called on mouse press to record the coordinates of the click */
    public void mousePressed(MouseEvent e) {
        last = new GPoint(e.getPoint());
        currentLabel = (GLabel)getElementAt(last);
    }

    /* Called on mouse drag to reposition the object */
    public void mouseDragged(MouseEvent e) {
        if (currentLabel != null) {
            currentLabel.move(e.getX() - last.getX(),
                    e.getY() - last.getY());
            last = new GPoint(e.getPoint());
        }
    }
}
