/**
 * erdos.java - 03/01/10 - 06/10/10 - 09/01/10 - 13/01/10
 * 
 * Auteur : Jean-Paul QUELEN
 * 
 * Applique le théorème de Erdös à un entier quelconque (sans les "BigInteger")
 *
 * ajout de main() et d'un Thread pour l'interruption éventuel du programme le 06/01/18 et modification le 28/08/22
 */

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.math.BigInteger;

public class erdos extends JPanel implements Runnable, ActionListener {
	static final long serialVersionUID = 220828L;
	JTextField tn;
	TextArea ta;
	JButton ok, stop;
	JButton efface;
	Thread t;

	public erdos() {
		setFont (new Font ("Arial, Helvetica, sans-serif", Font.PLAIN, 12));
		setBackground (Color.lightGray);
		setLayout (new BorderLayout ());
		JPanel p = new JPanel ();
		add (p, BorderLayout.NORTH);

// installe N = 1 et les bouton "Ok" et "Efface" dans le panneau "nord"
		p.add (new JLabel ("N ="));
		p.add (tn = new JTextField ("1", 10));
		p.add (ok = new JButton ("Ok"));
		ok.addActionListener (this);
		p.add (stop = new JButton ("Stop"));
		stop.addActionListener (this);
		p.add (efface = new JButton ("Efface"));
		efface.addActionListener (this);

// installe le champ de texte "ta" qui recevra les éléments de la suite dans le panneau central
		p = new JPanel();
		add (p);
		p.add (ta = new TextArea ("", 20, 50, TextArea.SCROLLBARS_VERTICAL_ONLY), BorderLayout.CENTER);
	}

	public void run() {
		Thread t1 = Thread.currentThread();
		try {
			long n = Integer.parseInt (tn.getText ());
			if (n < 0)
				ta.append ("Entrer un nombre entier positif\n");
			else {
				ta.append("\n");
				BigInteger pm = BigInteger.ONE;
				BigInteger pm2 = new BigInteger ("2");
				int lpm = 1;	// lpm contient le nombre de chiffres dans l'écriture binaire de pm
				while (t1 == t) {
					long m = 0;

// calcul de +/- 1^2 +/- 2^2 +/- 3^2...+/-lpm^2
					for (int i = 0; i < lpm; i ++) {
						int ip1c = (i + 1) * (i + 1);
						m += (pm.testBit (i))? ip1c : - ip1c;
					}
					if (m == n)
						break;								// on a trouvé => on peut sortir de la boucle
					else {
						pm = pm.add (BigInteger.ONE);		// on ajoute 1 à pm car
						if (pm.compareTo (pm2) == 0) {		// on essaie toutes les combinaisons +/-
							pm2 = pm2.add (pm2);			// dans la somme m
							lpm++;							// on a epuisé toutes les possibilités donc
							ta.append (".");				// on ajoute un terme dans la somme m
						}									// et on recommence...
					}
				}	// fin while
				if (t == null) {
					ta.append ("\nprocessus arrêté\n");
				} else {
					ta.append ("\n" + n + " = ");
					for (int i = 0; i < lpm; i ++) {
						ta.append (((pm.testBit (i)) ? " + " : " - ") + ((i + 1) * (i + 1)) + " ");
					}
					ta.append ("\n = ");
					for (int i = 0; i < lpm; i ++) {
						ta.append (((pm.testBit (i)) ? " + " : " - ") + (i + 1) + "²");
					}
				}
			}
		}
		catch (NumberFormatException nfe) {
			ta.append ("Entrer un nombre entier positif\n");
		}
	}

	public void actionPerformed (ActionEvent evt) {
		if (evt.getSource () == stop) {
			t = null;
		} else if (evt.getSource () == ok) {
			if (t != null) {
				t = null;
				try {
					Thread.sleep (1000);			// on attend une seconde
				}
				catch (InterruptedException ie) {}
			}
			t = new Thread (this);
			t.start();
		} else if (evt.getSource () == efface ) {
			ta.setText ("");
		}
	}


	public static void main (String args[]) {
		int w = 400;
		int h = 400;

		erdos e = new erdos ();
		JFrame f = new JFrame ("Erdös") ;
		f.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
		f.add (e) ;
		f.setSize (w, h) ;
		f.setVisible (true);
	}

}
