import java.applet.Applet;
import java.awt.Button;
import java.awt.GridLayout;
import java.awt.Label;
import java.awt.Panel;
import java.awt.TextArea;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

/**
 * An applet that allows to create and display two circles.
 * 
 * Provides 
 * 
 * - two input fields for specifying the coordinates of the center and the radius
 *   of the circles
 * 
 * - buttons for moving the circles up, down, left or right
 * 
 * - a text area which displays additional information about the circles
 */
public class CircleApplet extends Applet {

	/** A point specifieing the dircetion <i>right</i>. */
	final static Point RIGHT = new Point( 1, 0 );
	/** A point specifieing the dircetion <i>left</i>. */
	final static Point LEFT = new Point( -1, 0 );
	/** A point specifieing the dircetion <i>up</i>. */
	final static Point UP = new Point( 0, -1 );
	/** A point specifieing the dircetion <i>down</i>. */
	final static Point DOWN = new Point( 0, 1 );
	/** A text field for the {@code x}-coordinate of the first circle. */
	private TextField circle1x;
	/** A text field for the {@code y}-coordinate of the first circle. */
	private TextField circle1y;
	/** A text field for the radius of the first circle. */
	private TextField circle1radius;
	/** A button that moves the first circle up one unit. */
	private Button circle1Up;
	/** A button that moves the first circle down one unit. */
	private Button circle1down;
	/** A button that moves the first circle left one unit. */
	private Button circle1left;
	/** A button that moves the first circle right one unit. */
	private Button circle1right;
	/** A text field for the {@code x}-coordinate of the second circle. */
	private TextField circle2x;
	/** A text field for the {@code y}-coordinate of the second circle. */
	private TextField circle2y;
	/** A text field for the radius  of the second circle. */
	private TextField circle2radius;
	/** A button that moves the second circle up one unit. */
	private Button circle2up;
	/** A button that moves the second circle down one unit. */
	private Button circle2down;
	/** A button that moves the second circle left one unit. */
	private Button circle2left;
	/** A button that moves the second circle right one unit. */
	private Button circle2right;
	/** The output area in which additional information is displayed. */
	private TextArea outputArea;
	/** A canvas that displays the cirles. */
	private CircleCanvas canvas;
	/** The button that (re)paints the circles. */
	private Button btnOK;
	/** The first circle. */
	private Circle circle1;
	/** The second circle. */
	private Circle circle2;
	/** A point that is used to test if it is inside one of the circles. */
  private Point testPoint = new Point( 10, 10 );
	/** A text field for the {@code x}-coordinate of the test point. */
	private TextField testPointX;
	/** A text field for the {@code y}-coordinate of the test point. */
	private TextField testPointY;
	/** An action listener for all text fields. Only calls {@link #action()}. */
	private ActionListener acl = new ActionListener() {

		public void actionPerformed( ActionEvent e ) {
			action();
		}
	};

	/**
	 * <p>Updates the applet: the circles are repainted on the canvas and the
	 * information of the circles in the text area is updated.</p>
	 * <p>Is called whenever a button is pressed or any information is updated.</p>
	 */
	private void update() {
		canvas.repaint();
		outputCircleInformation();
		circle1x.setText( Double.toString( circle1.getCenter().getX() ) );
		circle1y.setText( Double.toString( circle1.getCenter().getY() ) );
		circle1radius.setText( Double.toString( circle1.getRadius() ) );
		circle2x.setText( Double.toString( circle2.getCenter().getX() ) );
		circle2y.setText( Double.toString( circle2.getCenter().getY() ) );
		circle2radius.setText( Double.toString( circle2.getRadius() ) );
	}

	/**
	 * Initializes the applet and generates the user interface. The {@link CircleCanvas},
	 * on which the circles are displayed is created, several buttons and text fields
	 * for setting coordinates of circles and move them around an text area that
	 * gives out additional information is created.
	 */
	@Override
	public void init() {
		setLayout( new GridLayout( 3, 1 ) );

		// create the canvas
		canvas = new CircleCanvas( this );

		Panel inputPanel = new Panel( new GridLayout( 5, 1 ) );

		Panel textPanel = new Panel();
		textPanel.add( new Label( "Bitte geben Sie koordinaten ein und drÃ¼cken sie OK um die Kreise zeichnen zu lassen." ) );
		inputPanel.add( textPanel );

		// input panel for the first circle
		Panel panelCircle1 = new Panel();
		circle1x = new TextField( "5", 3 );
		circle1y = new TextField( "5", 3 );
		circle1radius = new TextField( "45", 3 );

		circle1Up = new Button( "O" );
		circle1Up.addActionListener( new ActionListener() {

			public void actionPerformed( ActionEvent e ) {
				if( circle1 != null ) {
					circle1.translate( UP );
					update();
				}
			}
		} );
		circle1down = new Button( "U" );
		circle1down.addActionListener( new ActionListener() {

			public void actionPerformed( ActionEvent e ) {
				if( circle1 != null ) {
					circle1.translate( DOWN );
					update();
				}
			}
		} );
		circle1left = new Button( "L" );
		circle1left.addActionListener( new ActionListener() {

			public void actionPerformed( ActionEvent e ) {
				if( circle1 != null ) {
					circle1.translate( LEFT );
					update();
				}
			}
		} );
		circle1right = new Button( "R" );
		circle1right.addActionListener( new ActionListener() {

			public void actionPerformed( ActionEvent e ) {
				if( circle1 != null ) {
					circle1.translate( RIGHT );
					update();
				}
			}
		} );

		panelCircle1.add( new Label( "(x,y)-Koordinaten: " ) );
		panelCircle1.add( circle1x );
		panelCircle1.add( circle1y );
		panelCircle1.add( new Label( " Radius: " ) );
		panelCircle1.add( circle1radius );
		panelCircle1.add( circle1Up );
		panelCircle1.add( circle1down );
		panelCircle1.add( circle1left );
		panelCircle1.add( circle1right );
		circle1x.addActionListener( acl );
		circle1y.addActionListener( acl );
		circle1radius.addActionListener( acl );

		// input panel for circle 2
		Panel panelCircle2 = new Panel();
		circle2x = new TextField( "15", 3 );
		circle2y = new TextField( "66", 3 );
		circle2radius = new TextField( "15", 3 );

		circle2up = new Button( "O" );
		circle2up.addActionListener( new ActionListener() {

			public void actionPerformed( ActionEvent e ) {
				if( circle2 != null ) {
					circle2.translate( UP );
					update();
				}
			}
		} );
		circle2down = new Button( "U" );
		circle2down.addActionListener( new ActionListener() {

			public void actionPerformed( ActionEvent e ) {
				if( circle2 != null ) {
					circle2.translate( DOWN );
					update();
				}
			}
		} );
		circle2left = new Button( "L" );
		circle2left.addActionListener( new ActionListener() {

			public void actionPerformed( ActionEvent e ) {
				if( circle2 != null ) {
					circle2.translate( LEFT );
					update();
				}
			}
		} );
		circle2right = new Button( "R" );
		circle2right.addActionListener( new ActionListener() {

			public void actionPerformed( ActionEvent e ) {
				if( circle2 != null ) {
					circle2.translate( RIGHT );
					update();
				}
			}
		} );

		panelCircle2.add( new Label( "(x,y)-Koordinaten: " ) );
		panelCircle2.add( circle2x );
		panelCircle2.add( circle2y );
		panelCircle2.add( new Label( " Radius: " ) );
		panelCircle2.add( circle2radius );
		panelCircle2.add( circle2up );
		panelCircle2.add( circle2down );
		panelCircle2.add( circle2left );
		panelCircle2.add( circle2right );
		circle2x.addActionListener( acl );
		circle2y.addActionListener( acl );
		circle2radius.addActionListener( acl );

		// creates input fields for a point that is tested to be in the circles
		Panel testPanel = new Panel();
		testPointX = new TextField( "10.5", 3 );
		testPointY = new TextField( "10.5", 3 );
		testPointX.addActionListener( acl );
		testPointY.addActionListener( acl );
		testPanel.add( new Label( "Testpunkt (x,y)-Koordinaten: " ) );
		testPanel.add( testPointX );
		testPanel.add( testPointY );

		// creates the OK button
		Panel buttonPanel = new Panel();
		btnOK = new Button( "                         OK                         " );
		btnOK.addActionListener( new ActionListener() {

			public void actionPerformed( ActionEvent e ) {
				action();
			}
		} );
		buttonPanel.add( btnOK );

		inputPanel.add( panelCircle1 );
		inputPanel.add( panelCircle2 );
		inputPanel.add( testPanel );
		inputPanel.add( buttonPanel );

		// creates the output panel
		Panel outputPanel = new Panel();
		outputArea = new TextArea( "", 8, 55, TextArea.SCROLLBARS_VERTICAL_ONLY );
		outputArea.setEditable( false );
		outputPanel.add( outputArea );

		add( canvas );
		add( inputPanel );
		add( outputPanel );

		this.setSize( 800, 600 );
	}

	/**
	 * Returns the first circle (will be drawn in blue on the canvas).
	 * @return the first circle
	 */
	public Circle getCircle1() {
		return circle1;
	}

	/**
	 * Returns the second circle (will be drawn in green on the canvas).
	 * @return the second circle
	 */
	public Circle getCircle2() {
		return circle2;
	}
	/**
	 * Creates new instances of the two circles and displays them on the canvas.
	 */
	private void action() {
		//test to ignore false input
		if (circle1x.getText().isEmpty() || circle1y.getText().isEmpty() || circle2x.getText().isEmpty() ||
				circle2y.getText().isEmpty() || circle1radius.getText().isEmpty() || circle2radius.getText().isEmpty() ||
				testPointX.getText().isEmpty() || testPointY.getText().isEmpty() || 
				Double.parseDouble(circle1radius.getText()) < 0 || Double.parseDouble(circle2radius.getText()) < 0 ) {
			this.update();
			return;
		}
		Point center1 = new Point(Double.parseDouble(circle1x.getText()), Double.parseDouble(circle1y.getText()));
		Point center2 = new Point(Double.parseDouble(circle2x.getText()), Double.parseDouble(circle2y.getText()));
		double radius1 = Double.parseDouble(circle1radius.getText());
		double radius2 = Double.parseDouble(circle2radius.getText());
		circle1 = new Circle(radius1,center1);
		circle2 = new Circle(radius2,center2);
		testPoint = new Point(Double.parseDouble(testPointX.getText()), Double.parseDouble(testPointY.getText()));
		
		this.update();
        return;    
	}

	/**
	 * Writes the following information about the two circles to the output area.
	 * First the String representations of {@code toString()} is given out. Then
	 * the specified point is tested and it is given out if it is inside the
	 * circles or outside of them. Then the circles are tested to be equal. At last
	 * it is checked if the circles intersect each other.
	 */
	private void outputCircleInformation() {
		String s;
		
		s = ""+ circle1.toString()+"\n"+circle2.toString()+"\nTestpunkt: "+testPoint.toString()+
		"\n\nPunkt in Kreis1: "+circle1.contains(testPoint)+"\nPunkt in Kreis2: "+circle2.contains(testPoint)+
		"\nKreise gleich: "+circle1.equals(circle2)+"\nKreise schneiden sich: "+circle1.intersects(circle2)+
		"\nKreis1 enthält vollständig Kreis2: "+circle1.contains(circle2)+"\nKreis2 enthält vollständig Kreis1: "+circle2.contains(circle1)+
		"\n\nFlächen Kreis1, Kreis2: "+Math.round(circle1.getArea())+" , "+Math.round(circle2.getArea())+
		"\nUmfang Kreis1, Kreis2: "+Math.round(circle1.getPerimeter())+" , "+Math.round(circle2.getPerimeter());
		outputArea.setText(s);
		return;
	}

}
