/*  Monte-Carlo simulation code for statistical physics
    Copyright (C) 2001-2005  Sylvain Reynal
    
    Département de Physique
    Ecole Nationale Supérieure de l'Electronique et de ses Applications (ENSEA)
    6, avenue du Ponceau,    
    F-95014 CERGY CEDEX

    et
    
    Laboratoire de Physique Théorique et Modélisation (LPTM)
    Université de Cergy-Pontoise - Site de Neuville
    F-95031 CERGY CEDEX
    
	
    Tel : 00 +33 130 736 245
    Fax : 00 +33 130 736 667
    e-mail : reynal@ensea.fr
    web page : http://www.ensea.fr/staff/reynal/
*/

package fr.ensea.montecarlo;

import fr.ensea.Version;
import fr.ensea.Localizer;
import fr.ensea.chart.*;
import fr.ensea.montecarlo.data.*;
import fr.ensea.montecarlo.model.*;
import fr.ensea.montecarlo.canonical.*;
import fr.ensea.montecarlo.misc.*;

import java.awt.*;
import java.awt.event.*;
import java.applet.Applet;
import java.text.NumberFormat;
import java.util.Locale;

/**
 * UI controller. This is the hub that holds together several classes involved in the simulation, including
 * the algorithm thread, graphs and widgets, event listeners, and data bags.
 */
public class MCApplet extends AbstractApplet  {

	
	private MCSimulationCustomizer configurationPanelFR;
	

	// --- RG only ---
	private RenormalizationPanel renormalizationPanelFR;
	private boolean isRGActive;
	
	////////////////////////////////////////////////////////

	public MCApplet(){
		super();
	}
	
	public MCApplet(String[] args){
		super(args);
	}

	/**
	 * Returns information about the parameters that are understood by this applet.
	 */
	public String[][] getParameterInfo(){
		String pinfo[][] = {
			{"algorithm", "\"metropolis\"|\"wolff\"", Localizer.get("paramInfo1")},
			{"Q",	"2-11",		Localizer.get("paramInfo2")},
			{"L", 	"int", 	Localizer.get("paramInfo3")},
			{"MCTherm", 	"int", 	Localizer.get("paramInfo4")},
			{"MCMeas", 	"int", 	Localizer.get("paramInfo5")},
			{"sweep",  "\"true\"|\"false\"",   Localizer.get("paramInfo6")},
			{"kT",  "double",   Localizer.get("paramInfo7")},
			{"kTstart",  "double",   Localizer.get("paramInfo8")},
			{"kTend",  "double",   Localizer.get("paramInfo9")},
			{"kTsteps",  "int",   Localizer.get("paramInfo10")},
			{"lang",  "en|fr",   Localizer.get("paramInfo11")},
			{"model",  "Potts|PottsRG|AFIsing",   Localizer.get("paramInfo12")}
		};
		return pinfo;
	}

	/**
	 * Called by the browser or applet viewer to inform this applet that it has been loaded into the system.
	 */
	public void init(){
		//System.out.println("init");
		String lang=getParameter("lang");
		if (lang==null || lang.equals("")) lang="en";
		Localizer.init(new Locale(lang));

		//this.graphPreferredSize = new Dimension(getSize().width/4, getSize().height/4);

		String paramQ, paramL, paramKT, paramKTstart, paramKTend, paramKTsteps, paramIsKTSweep;
		String paramMCTherm,paramMCMeas,paramMCAlgo, paramModel;
		paramQ = getParameter("Q");
		paramL = getParameter("L");
		paramIsKTSweep=getParameter("sweep");
		paramKT = getParameter("kT");
		paramKTstart=getParameter("kTstart");
		paramKTend=getParameter("kTend");
		paramKTsteps=getParameter("kTsteps");
		paramMCTherm=getParameter("MCTherm");
		paramMCMeas=getParameter("MCMeas");
		paramMCAlgo=getParameter("algorithm");
		paramModel=getParameter("model");
		
		Montecarlo defAlgo;
		boolean defIsKTsweep=true;
		int defQ=5, defL=50,defKTsteps=10,defMCTherm=100,defMCMeas=1000;
		double defKT=0.5, defKTstart=0.2, defKTend=1.0;
		try {
			if (paramQ!=null) defQ = Integer.parseInt(paramQ);
			if (paramL!=null) defL = Integer.parseInt(paramL);
			if (paramKT!=null) defKT = Double.valueOf(paramKT).doubleValue();
			if (paramKTstart!=null) defKTstart = Double.valueOf(paramKTstart).doubleValue();
			if (paramKTend!=null) defKTend = Double.valueOf(paramKTend).doubleValue();
			if (paramKTsteps!=null) defKTsteps = (int)Double.valueOf(paramKTsteps).doubleValue();
			if (paramIsKTSweep!=null) defIsKTsweep = paramIsKTSweep.equals("true");
			if (paramMCTherm!=null) defMCTherm = (int)Double.valueOf(paramMCTherm).doubleValue();
			if (paramMCMeas!=null) defMCMeas = (int)Double.valueOf(paramMCMeas).doubleValue() + defMCTherm;
		}
		catch (NumberFormatException nfe){
			showStatus(nfe.toString());
		}
		if (paramModel!=null) {
			isRGActive=false;
			if (paramModel.equals("AFIsing")) lattice = new AFIsingLattice(defL);
			else if (paramModel.equals("PottsRG")) {
				defL=PottsLattice.floorToPowerOf2(defL);
				lattice = new PottsLattice(defQ, defL); // ising !
				isRGActive = true;
			}
			else lattice = new PottsLattice(defQ, defL); // "Potts" by default
		}
		if (lattice==null) lattice = new PottsLattice(defQ, defL);

		// init data bags:
		samplesBag = new SamplesBag(defMCTherm);
		// init algo thread:
		if (defIsKTsweep) algoThread = new MCSimulationThread(this, defKTstart, defKTend, defKTsteps); // metropolis by default
		else algoThread = new MCSimulationThread(this, defKT);
		if (paramMCAlgo!=null && paramMCAlgo.equals("wolff")) 
			((MCSimulationThread)algoThread).setAlgorithm(MCSimulationThread.WOLFF);
		algoThread.setNumberMCSteps(defMCMeas);

		// RG specific:
		if (isRGActive) {
			((MCSimulationThread)algoThread).activateRG();
			renormalizationPanelFR = new RenormalizationPanel(this);
		}

		configurationPanelFR = new MCSimulationCustomizer(this, (MCSimulationThread)algoThread, defKT);
		initUI();
	}

	////////////////////////////////////////////////////
	//// UI
	////////////////////////////////////////////////////

	
	public void toggleConfigurationPanel(){
		configurationPanelFR.setVisible(!configurationPanelFR.isVisible());
	}
	
	public RenormalizationPanel getRenormalizationPanel(){
		return this.renormalizationPanelFR;
	}

	///////////////////////////////////////////////////////////////
	//// Accessors
	///////////////////////////////////////////////////////////////

	public Montecarlo getAlgorithm(){
		return ((MCSimulationThread)algoThread).getAlgorithm();
	}
	
	public boolean isRGActive(){
		return isRGActive;
	}

	////////////////////////////////////////
	/// stand-alone mode
	////////////////////////////////////////
	public static void main(String[] args){
		MCApplet a = new MCApplet(args);
	}

	
}

