package jfractionlab.exerciseDialogs;

import info.clearthought.layout.TableLayout;

import java.awt.Color;
import java.awt.Container;
import java.awt.HeadlessException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;

import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JOptionPane;

import jfractionlab.FractionMaker;
import jfractionlab.HelpStarter;
import jfractionlab.JFractionLab;
import jfractionlab.MyJTextField;
import jfractionlab.displays.FractionAsRectangle;
import jfractionlab.displays.FractionLine;
import jfractionlab.jflDialogs.UsabilityDialog;
import jfractionlab.jflDialogs.WannaReduceQuestion;

public class DecimalToFraction extends ExerciseDialog implements
		ActionListener, KeyListener {
	static final long serialVersionUID = JFractionLab.serialVersionUID;
	// GUI
	private JLabel lb_instruction = new JLabel("", JLabel.CENTER);
	private MyJTextField tf_numerator_1 = new MyJTextField(3);
	private MyJTextField tf_denominator_1 = new MyJTextField(3);
	private MyJTextField tf_numerator_2 = new MyJTextField(3);
	private MyJTextField tf_denominator_2 = new MyJTextField(3);
	private MyJTextField tf_decimal = new MyJTextField(3);

	FractionAsRectangle pizza1 = new FractionAsRectangle();
	FractionAsRectangle pizza2 = new FractionAsRectangle();

	private FractionMaker fraction = new FractionMaker();
	private double decimal;
	private int numerator_1;
	private int denominator_1;
	private int numerator_2;
	private int denominator_2;
	
	
	/**
	 * 
	 * @param owner
	 * @param lx
	 * @param ly
	 * @param sx
	 * @param sy
	 * @throws HeadlessException
	 */
	public DecimalToFraction(JFractionLab owner, int lx, int ly, int sx, int sy)
			throws HeadlessException {
		super(lx, ly, sx, sy);

		setTitle(lang.Messages.getString("decimal_to_fraction"));
		btn_continue = new JButton(lang.Messages.getString("continue"));
		btn_end = new JButton(lang.Messages.getString("end"));

		this.owner = owner;
		// Menu
		rb_random.addActionListener(this);
		jmOptions.add(rb_random);
		rb_custom.addActionListener(this);
		jmOptions.add(rb_custom);
		jmOptions.addSeparator();
		
		rb_no_reducing.addActionListener(this);
		jmOptions.add(rb_no_reducing);
		rb_reducing.addActionListener(this);
		jmOptions.add(rb_reducing);
		
		jmb.add(jmOptions);
		jmiHelp.addActionListener(this);
		jmb.add(jmHelp);
		setJMenuBar(jmb);

		//
		double sizes[][] = { {
				// Spalten
				5, // 00
				TableLayout.FILL, // 01:
				TableLayout.FILL, // 02:
				TableLayout.FILL, // 03:
				20, // 04: equal
				TableLayout.FILL, // 05:
				TableLayout.FILL, // 06:
				TableLayout.FILL, // 07
				20, // 08: equal
				TableLayout.FILL, // 09
				TableLayout.FILL, // 10:
				TableLayout.FILL, // 11: space
				TableLayout.FILL, // 12: buttons
				5 // 13
				}, {
						// Zeilen
						5, // 00
						TableLayout.FILL, // 01: instructionlabel
						0.1, // 02: numerator
						15, // 03: fractionbar
						0.1, // 04: denominator
						0.25, // 05: first pizza
						10, // 06
						0.25, // 07: second pizza
						TableLayout.FILL, // 08: infolabel
						5 // 09
				} };
		Container content = getContentPane();
		content.setLayout(new TableLayout(sizes));
		content.setBackground(Color.white);

		lb_instruction.setFont(JFractionLab.infofont);
		content.add(lb_instruction, "1,1,9,1");

		// decimal
		addTextField(tf_decimal);
		tf_decimal.addKeyListener(this);
		content.add(tf_decimal, "2,2,2,4,c,c");

		// equal
		JLabel lb_equal1 = new JLabel("", JLabel.CENTER);
		lb_equal1.setFont(JFractionLab.infofont);
		lb_equal1.setText("=");
		content.add(lb_equal1, "4,3");

		// first fraction
		addTextField(tf_numerator_1);
		tf_numerator_1.addKeyListener(this);
		content.add(tf_numerator_1, "6,2,c,b");
		content.add(new FractionLine(), "6,3");
		addTextField(tf_denominator_1);
		content.add(tf_denominator_1, "6,4,c,t");

		// equal
		JLabel lb_equal2 = new JLabel("", JLabel.CENTER);
		lb_equal2.setFont(JFractionLab.infofont);
		lb_equal2.setText("=");
		content.add(lb_equal2, "8,3");

		// second fraction
		addTextField(tf_numerator_2);
		tf_numerator_2.addKeyListener(this);
		content.add(tf_numerator_2, "10,2,c,b");
		content.add(new FractionLine(), "10,3");
		addTextField(tf_denominator_2);
		tf_denominator_2.addKeyListener(this);
		content.add(tf_denominator_2, "10,4,c,t");

		// first pizza
		content.add(pizza1, "1,5,9,5");

		// second pizza
		content.add(pizza2, "1,7,9,7");

		// infolabel
		lb_info.setFont(JFractionLab.infofont);
		lb_info.setText(lang.Messages.getString("you_just_need_nb_and_enter"));
		content.add(lb_info, "1,8,9,8");

		// Buttons
		btn_continue.addKeyListener(this);
		btn_continue.addActionListener(this);
		content.add(btn_continue, "12,2,f,b");

		btn_end.addActionListener(this);
		content.add(btn_end, "12,4,f,t");

		points = owner.points_decimalToFraction;

		pdsp.setText(String.valueOf(points));
		content.add(pdsp, "12,5,12,7,c,c");

		makeProblem();
		String[] ar_howto = { "howto_nb_and_enter",
				"howto_option_type_of_exercise" };
		new UsabilityDialog(ar_howto);
	}// Konstruktor

	/**
	 * 
	 *
	 */
	protected void makeProblem() {
		// System.out.println("makeProblem");
		if (smallNumbers){
//			decimal = fraction.mkEasyDecimalFraction(true);
			decimal = fraction.mkDecimalFraction(true);
		}else{
			decimal = fraction.mkDecimalFraction(false);
		}
		

		denominator_1 = calculateDenominator1(decimal);
		numerator_1 = calculateNumerator1(decimal);

		DecimalFormat df = new DecimalFormat();

		tf_decimal.setText(df.format((decimal)));
		tf_denominator_1.setText(String.valueOf(denominator_1));

		pizza1.drawEmptyPizzaAsRectangle(denominator_1, false, false);
		pizza2.noPizzaAsRectangle();

		tf_numerator_1.setEditable(true);
		tf_numerator_1.requestFocusInWindow();
	}
	
	private int calculateDenominator1(double decimal) {
		BigDecimal bigd = new BigDecimal(Double.toString(decimal)).setScale(2, RoundingMode.HALF_EVEN);
		BigDecimal b100 = new BigDecimal("100");
		BigDecimal b10 = new BigDecimal("10");
		BigDecimal b0 = new BigDecimal("0");

		BigDecimal product = bigd.multiply(b100).setScale(2);
		if (product.remainder(b10).compareTo(b0) == 0){
				denominator_1 = 10;
				return 10;
			} else {
				denominator_1 = 100;
				return 100;
			}
	}

	private int calculateNumerator1(double decimal) {
		BigDecimal bigd = new BigDecimal(Double.toString(decimal)).setScale(2, RoundingMode.HALF_EVEN);
		BigDecimal bigDenominator = new BigDecimal(denominator_1);
		BigDecimal bigNumerator = bigd.multiply(bigDenominator);
		numerator_1 = bigNumerator.intValueExact();
		return bigNumerator.intValueExact();
	}

	/**
	 * 
	 *
	 */
	protected void nextProblem() {
		clearTextFields();
		lb_info.setText("");
		if (bl_randomProblem == true) {
			makeProblem();
		} else {

			pizza1.noPizzaAsRectangle();
			pizza2.noPizzaAsRectangle();

			tf_decimal.setText("");
			tf_decimal.setEditable(true);
			tf_decimal.requestFocusInWindow();
		}
	}

	/**
	 * 
	 */
	public void actionPerformed(ActionEvent e) {

		Object obj = e.getSource();
		if (obj == btn_continue) {
			nextProblem();
		} else if (obj == btn_end) {
			close_it();
		} else if (obj == jmiHelp) {
			new HelpStarter(lang.Messages.getLocale().toString(), "decimal");
		} else if (obj == rb_random) {
			// System.out.println("rb_random");
			// the program is in "custom-mode" actually
			// it should switch to "random-mode"
			bl_randomProblem = true;
			nextProblem();
		} else if (obj == rb_custom) {
			// System.out.println("rb_custom");
			// the program is in "random-mode" actually
			// it should switch to "custom-mode"
			bl_randomProblem = false;
			nextProblem();
		}
		else if (obj == rb_reducing){
			//System.out.println("rb_reducing");
			//the program is in "no reduce mode" actually
			//it should switch to "reduce-mode"
			bl_with_reducing = true;
			nextProblem();
		}else if (obj == rb_no_reducing){
			//System.out.println("rb_no_reucing");
			//the program is in "reduce mode" actually
			//it should switch to "no reduce-mode"
			bl_with_reducing = false;
			nextProblem();
		}
		/*
		 * else if(obj == jmiCreateWorkSheet){ new WorkSheetDialog(
		 * ExerciseGenerator.FRACTIONS_TO_DECIMAL,
		 * lang.Messages.getString("fraction_to_decimal") ); }
		 */

	}// actionPerformed

	public void keyPressed(KeyEvent event) {

		Object obj = event.getSource();
		int key = event.getKeyCode();
		lb_info.setText("");

		if (obj == btn_continue & key == KeyEvent.VK_ENTER) {
			nextProblem();
		} else if (obj == btn_end & key == KeyEvent.VK_ENTER) {
			close_it();
		} else if (obj == tf_decimal & key == KeyEvent.VK_ENTER 	&& tf_decimal.isEditable()) {
			// custom exercise
			if (readInputDouble(tf_decimal) != null) {
				double dec = readInputDouble(tf_decimal);
				if (dec >= 1 || dec <= 0) {
					lb_info.setText(lang.Messages
							.getString("decimal_out_of_range"));
					//FIXME not more than 2 digits!!
					return;
				}
				
				
				decimal = dec;
				denominator_1 = calculateDenominator1(decimal);
				fraction.setNenner_1(denominator_1);

				tf_denominator_1.setText(String.valueOf(denominator_1));

				pizza1.drawEmptyPizzaAsRectangle(denominator_1, false, false);
				pizza2.noPizzaAsRectangle();

				tf_decimal.setEditable(false);
				tf_numerator_1.setEditable(true);
				tf_numerator_1.requestFocusInWindow();
			}
		} else if (obj == tf_numerator_1 & key == KeyEvent.VK_ENTER && tf_numerator_1.isEditable()) {

			if (readInputInt(tf_numerator_1) != null) {
				int num = readInputInt(tf_numerator_1);
				numerator_1 = calculateNumerator1(decimal);
				if (numerator_1 == num) {
					pizza1.drawPizzaAsRectangle(num, denominator_1,Color.yellow, false, false);
					tf_numerator_1.setEditable(false);
					if(JFractionLab.greatestCommonDivisor(numerator_1, denominator_1) != 1){
						//reducable
						if(bl_with_reducing){
							tf_numerator_1.setEditable(false);
							tf_numerator_2.setEditable(true);
							tf_numerator_2.requestFocusInWindow();
						}else{
							new WannaReduceQuestion(this);
							this.toFront(); //damit das fenster wieder aktiv ist und den focus wieder hat.
							if(bl_wannaReduceQuestion_AnswerIsYes){
								tf_numerator_1.setEditable(false);
								tf_numerator_2.setEditable(true);
								tf_numerator_2.requestFocusInWindow();
							}else{
								points++;
								pdsp.setText(String.valueOf(points));
								owner.setPoints(points, "decimalToFraction");
								btn_continue.requestFocusInWindow();
							}
						}
					}else{
						//not recuable
						tf_numerator_1.setEditable(false);
						lb_info.setText(lang.Messages.getString("that_is_right"));
						points++;
						pdsp.setText(String.valueOf(points));
						owner.setPoints(points, "decimalToFraction");
						btn_continue.requestFocusInWindow();
					}
				} else if (numerator_1 < num) {
					pizza1.drawPizzaAsRectangle(num, denominator_1, Color.red,false, false);
					lb_info.setText(decimal + " * " + denominator_1 + " = ?");
				} else {
					pizza1.drawPizzaAsRectangle(num, denominator_1, Color.red,false, false);
					lb_info.setText(decimal + " * " + denominator_1 + " = ?");
				}
			}
		}else if (obj == tf_numerator_2 & key == KeyEvent.VK_ENTER && tf_numerator_2.isEditable()) {
			if (readInputInt(tf_numerator_2) != null) {
				int prov = readInputInt(tf_numerator_2);
				boolean isOK = false;
				try {
					if(numerator_1 % prov == 0){
						if(denominator_1 % (numerator_1 / prov) == 0){
							isOK = true;
						}
					}
				} catch (Exception e) {	}
				if(isOK){
					numerator_2 = prov;
					tf_numerator_2.setEditable(false);
					tf_denominator_2.setEditable(true);
					tf_denominator_2.requestFocusInWindow();
				}else{
					lb_info.setText(lang.Messages.getString("wrong_numerator"));
					tf_numerator_2.setText("");
				}
			}
		}
		else if (obj == tf_denominator_2 & key == KeyEvent.VK_ENTER && tf_denominator_2.isEditable()) {
			if (readInputInt(tf_denominator_2) != null) {
				if(readInputInt(tf_denominator_2) <= 100){
					denominator_2 = readInputInt(tf_denominator_2);
					int reduceFactor = numerator_1 / numerator_2;
					try {
						if(denominator_1 / reduceFactor == denominator_2){
							//fraction is ok
							if(JFractionLab.greatestCommonDivisor(numerator_2, denominator_2) != 1){
								//fraction is reducable
								pizza2.drawPizzaAsRectangle(numerator_2, denominator_2, Color.pink,false,false);
								lb_info.setText(lang.Messages.getString("reduce_better"));
								tf_denominator_2.setEditable(false);
								tf_numerator_2.setEditable(true);
								tf_numerator_2.requestFocusInWindow();
							}else{
								//fraction is NOT reducable
								pizza2.drawPizzaAsRectangle(numerator_2, denominator_2, Color.yellow,false,false);
								lb_info.setText(lang.Messages.getString("that_is_right"));
								points++;
								points++;
								pdsp.setText(String.valueOf(points));
								owner.setPoints(points, "decimalToFraction");
								btn_continue.requestFocusInWindow();
							}
						}else{
							//fraction is not ok
							lb_info.setText(lang.Messages.getString("n_and_dn_do_not_match"));
							tf_denominator_2.setEditable(false);
							tf_numerator_2.setEditable(true);
							tf_numerator_2.requestFocusInWindow();
						}
					} catch (Exception e) {
						JOptionPane.showMessageDialog(this, "Error, DecimalToFraction/denominator_1 / reduceFactor\n please send an email to gnugeo@gnugeo.de");
					}
				}else{
					tf_denominator_2.setEditable(false);
					tf_numerator_1.setEditable(true);
					tf_numerator_1.requestFocusInWindow();
					lb_info.setText(lang.Messages.getString("denominator_maximal_100"));
				}
			}else{
				tf_denominator_2.setText("");
				lb_info.setText(lang.Messages.getString("nb_is_not_correct"));
			}
			
		}
	}// keyPressed

	public void keyTyped(KeyEvent event) {
	}

	public void keyReleased(KeyEvent event) {
	}
}// class