package visualisationListe;

import java.applet.Applet;
import java.awt.Canvas;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Panel;
import java.awt.Polygon;
import java.util.Random;


@SuppressWarnings("serial")
/**
 * La classe MontreListe réutilise les fonctionnalités de la classe java.applet.Applet
 * Elle ajoute ses initialisations et ses actions propres.
 */
public class MontreListe extends Applet{
	Liste laListe;
	Panel lePanel;
/**
 * appelée lors de l'initialisation de l'applet, cette méthode initialise la liste chaînée et
 * demande son apparition	
 */
	public void init(){
		laListe=new Liste();
		montre();
		}
	
/**
 * Cette méthode interne est appelée pour dessiner toutes les cellules de la liste,
 * lorsque celle-ci subit une modification. L'applet contient un panel qui contient
 * lui-même les dessins des cellules. Puisque la liste vient d'être créée ou modifiée,
 * le panel doit être re-découpé et re-dessiné. Il est d'abord supprimé, puis recréé et empli avec
 * les dessins des cellules
 */
	private void montre(){
		if (getComponentCount()!=0)	remove(0);
		lePanel=new Panel();
		add(lePanel); 
		lePanel.setLayout(new GridLayout(1, laListe.nbValeurs));
		Liste laListeLocale=laListe;
		for (int i=0; i<laListe.nbValeurs; i++){
			MontreCellule laCellule=new MontreCellule(laListeLocale.laValeur.intValue());
			laCellule.setSize(getSize().width/laListe.nbValeurs, getSize().height);
			laListeLocale=laListeLocale.laSuite;
			if (i==0) laCellule.laPremiere=true;
			if (i==laListe.nbValeurs-1) laCellule.laDerniere=true;
			lePanel.add(laCellule);
			}
		validate();
		}
	
/**
 * méthode destinée à être appelée de l'extérieur (par l'autre applet) quand l'utilisateur
 * vient d'ajouter une valeur
 * @throws Exception 
 */
	public void ajoute(int valeur){
		laListe.ajoute(valeur);
		montre();
		}
		
/**
 * méthode destinée à être appelée de l'extérieur (par l'autre applet) quand l'utilisateur
 * vient d'enleverune valeur
 */
	public void enleve(int valeur){
		laListe.enleve(valeur);
		montre();
		}
		
	}

@SuppressWarnings("serial")
/**
 * cette classe se charge du dessin d'une cellule
 */
class MontreCellule extends Canvas{
	int laValeur;
	boolean laPremiere, laDerniere;
	Polygon laPointe; // la pointe de la flèche
	
	public MontreCellule(int uneValeur){
		laValeur=uneValeur;
		setSize(100, 200);
		laPremiere=false; laDerniere=false;
		}
/**
 * méthode appelée par le gestionnaire d'interface chaque fois qu'une cellule doit être re-dessinée
 * notamment la première fois qu'elle apparaît ou quand elle est démasquée
 */
	public void paint(Graphics cg){
		int MARGE = Math.min(getSize().width, getSize().height)/4;
		cg.drawRect(MARGE, MARGE, getSize().width-2*MARGE, getSize().height-2*MARGE);
		cg.drawLine(MARGE, getSize().height/2, getSize().width-MARGE, getSize().height/2);
		cg.drawString(laValeur+"",(int)(1.75*MARGE), (int)(getSize().height*0.75));
		if (!laDerniere)	cg.drawLine(getSize().width/2, getSize().height/4, getSize().width, getSize().height/4);
		if (!laPremiere)	{
			laPointe=new Polygon();
			cg.drawLine(0, getSize().height/4, MARGE, getSize().height/4);
			laPointe.addPoint(MARGE, getSize().height/4);
			laPointe.addPoint((int)(0.5*MARGE), (int)(getSize().height/4-0.75*MARGE));
			laPointe.addPoint((int)(0.5*MARGE), (int)(getSize().height/4+0.75*MARGE));
			cg.fillPolygon(laPointe);
			}
		}
	}

/**
 * implantation simplissime de la classe Liste (modèle de cette application).
 * Une liste est vue ici comme une valeur de type Integer et une sous-liste.
 * @author jpf
 *
 */
class Liste{
	static Random r;
	Integer laValeur;
	Liste laSuite;
	int nbValeurs; // mémorisera le nombre de cellules
	
/**
 * constructeur par défaut, qui crée une liste de 5 cellules avec des valeurs aléatoires
 */
	public Liste(){
		r=new Random();
		laValeur=new Integer(Math.abs(r.nextInt()%100)+1);
		nbValeurs=1;
		for (int i=1; i<5; i++) ajoute(Math.abs(r.nextInt()%100)+1);
//		System.out.println(this);
		}

/**
 * constructeur avec valeur entière, qui crée une liste d'une seule cellule avec la valeur donnée
 * @param val la valeur indiquée
 */
	public Liste(int val){
		laValeur=new Integer(val);
		nbValeurs=1;
		}

/**
 * méthode qui ajoute dans la liste une nouvelle cellule contenant la valeur indiquée.
 * Si la valeur de la liste donnée est absente, la valeur indiquée est inscrite dedans
 * Si la valeur indiquée est inférieure à la valeur de la liste (de la cellule de tête de la liste)
 * une nouvelle instance de la classe Liste est crée, reçoit la valeur donnée et est inscrite
 * en tête, recevant comme sous-liste la liste de départ
 * S'il n'y a pas de sous-liste, une nouvelle liste contenant la valeur indiquée est créée et
 * inscrite comme sous-liste
 * S'il y a une sous-liste, la fonction s'appelle récursivement pour que la valeur indiquée
 * soit inscrite plus loin
 * @param laValeurAjoutee
 * @throws Exception si la liste est mal ordonnée, avant ou après
 */
	public void ajoute(int laValeurAjoutee){
		if (laValeur==null)	{
			laValeur=new Integer(laValeurAjoutee);
			nbValeurs=1;
			return;
			}
		if (laValeurAjoutee<laValeur.intValue())	{
			Liste laNouvelle=new Liste(laValeur.intValue());
			laNouvelle.laSuite=laSuite;
			laValeur=new Integer(laValeurAjoutee);
			laSuite=laNouvelle;
			laNouvelle.nbValeurs=nbValeurs;
			nbValeurs++;
			return;
			}
		if (laSuite==null)	{
			laSuite=new Liste(laValeurAjoutee);
			nbValeurs=2;
			}
		else	{
			laSuite.ajoute(laValeurAjoutee);
			nbValeurs++;
			}
		return;
		}

/**
 * méthode appelée pour supprimer une cellule de la liste.
 * Si la liste est vide, elle ne fait rien
 * Si la valeur indiquée est inférieure à celle de la première cellule, elle ne peut pas se trouver
 * plus loin, la méthode ne fait rien
 * Si la valeur indiquée est plus grande que celle de la première cellule, la méthode s'appelle
 * récursivement pour que la suppression se fasse dans sa sous-liste
 * Si la valeur est bien celle que l'on veut supprimer et qu'il y a une sous-liste, on inscrit
 * dans notre cellule la valeur de la cellule suivante, puis on décroche cette cellule suivante
 * en reliant directement notre cellule à celle qui est encore après
 * Si c'est la bonne valeur et la dernière cellule, on vide simplement cette cellule, qui sera
 * remplie plus tard, si un ajout se produit en queue de liste.
 * @param laValeurEnlevee
 */
	public void enleve(int laValeurEnlevee){
		if (laValeur==null) return;
		if (laValeurEnlevee < laValeur.intValue())	return;
		if (laValeurEnlevee > laValeur.intValue())	{
			laSuite.enleve(laValeurEnlevee);
			nbValeurs--;
			return;
			}
		if (laSuite!=null)	{
			laValeur=laSuite.laValeur;
			laSuite=laSuite.laSuite;
			}
		else	laValeur=null;
		nbValeurs--;
		return; 
		}

/**
 * méthode permettant, lors de la mise au point, de voir les valeurs de la liste.
 */
	public String toString(){
		String resultat=" La liste contient "+nbValeurs+" elements : "+laValeur+" ";
		if (laSuite != null) resultat+=laSuite.toString();
		return resultat;
		}
	}