package org.lucci.madhoc;

import java.awt.Color;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.net.URL;
import java.util.Properties;

import javax.mail.Message;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

import org.lucci.config.ConfigurationException;
import org.lucci.config.TypedConfiguration;
import org.lucci.madhoc.gui.SimulationFrame;
import org.lucci.madhoc.script.Batch;
import org.lucci.madhoc.simulation.MadhocSimulation;
import org.lucci.madhoc.simulation.Simulation;
import org.lucci.madhoc.simulation.measure.MeasureHistory;
import org.lucci.madhoc.simulation.measure.Sensor;
import org.lucci.madhoc.simulation.projection.Projection;
import org.lucci.madhoc.util.Utilities;
import org.lucci.math.relation.RelationIO;
import org.lucci.up.EPSPlotter;
import org.lucci.up.data.Figure;
import org.lucci.up.data.FigureFactory;
import org.lucci.up.system.Space;

import com.l2fprod.gui.plaf.skin.Skin;
import com.l2fprod.gui.plaf.skin.SkinLookAndFeel;

/*
 * Created on Aug 18, 2004
 */

/*
 * Created on Aug 18, 2004
 */

/**
 * 
 * For each broadcasting protocol: vary the density of mobile stations in [500,
 * 10000] and measures the hosting rate, emission efficiency each mesure being
 * the average of 10 measures
 * 
 * 
 * 
 * @author luc.hogie
 */
public class Madhoc extends Batch
{
    public static void main(String[] args) throws Throwable
    {
        new Madhoc(args);
    }

    public Madhoc(String[] args) throws Throwable
    {
        try
        {
            TypedConfiguration config = Utilities.getConfiguration(args);
            MadhocSimulation simulation = Utilities.getSimulation(config);

            String simulation_mode = simulation.getConfiguration().getString("simulation_interaction_mode");

            if (simulation_mode.equalsIgnoreCase("console"))
            {
                mode_console(args, simulation);
            }
            else if (simulation_mode.equalsIgnoreCase("graphical"))
            {
                mode_gui(simulation);
            }
            else
            {
                throw new IllegalArgumentException("simulation modes '" + simulation_mode + "' is not defined");
            }

            // Collection unredKeys = config.getUnredKeys();
            //          
            // if (!unredKeys.isEmpty())
            // {
            // System.out.println("Warning, the following configuration keys are
            // unsed: " + unredKeys);
            // }
        }
        catch (Throwable ex)
        {
            ex.printStackTrace();
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            PrintStream ps = new PrintStream(bos);
            ex.printStackTrace(ps);
            ps.close();
            bos.close();
            String trace = new String(bos.toByteArray());

            File f = new File("last-error.txt");
            FileOutputStream fos = new FileOutputStream(f);
            fos.write(trace.getBytes());
            fos.close();

            System.err.println("Error: " + ex.getMessage());
            System.err.println("The file \"" + f.getAbsolutePath() + "\" contains the stack trace");

            // try to mail the error
            try
            {
                Properties props = System.getProperties();
                if (props.get("mail.smtp.host") == null)
                    props.put("mail.smtp.host", "localhost");
                Session session = Session.getDefaultInstance(props, null);
                MimeMessage message = new MimeMessage(session);
                message.setFrom(new InternetAddress(props.getProperty("user.name")));
                message.addRecipient(Message.RecipientType.TO, new InternetAddress("luc.hogie@laposte.net"));
                message.setSubject("Madhoc exception");
                message.setText(trace);
                Transport.send(message);
            }
            catch (Throwable e)
            {
            }
        }
    }

    public void mode_console(String[] args, MadhocSimulation simulation) throws Throwable
    {
        // until all applications terminates
        while (!simulation.findRunningApplications().isEmpty())
        {
            simulation.iterate();
        }

        byte[] output = getSimulationOuput(simulation);

        if (args.length == 0)
        {
            System.out.println(new String(output));
        }
        else
        {
            String simulationName = simulation.getConfiguration().getString("simulation_name");

            if (simulationName == null || simulationName.length() == 0)
            {
                simulationName = "unnamed-simulation";
            }

            File f = new File(simulationName + "-result.txt");
            FileOutputStream fos = new FileOutputStream(f);
            fos.write(output);
            fos.close();
        }
    }

    private byte[] getSimulationOuput(MadhocSimulation simulation)
    {
        // String simulation_output_format=
        // simulation.getConfiguration().getString("simulation_output_format");
        //        
        // if (simulation_output_format.equals("text"))
        {
            return simulation.getOutputAsText().getBytes();
        }
        // else if (simulation_output_format.equals("binary"))
        // {
        // return simulation.getOutputAsText();
        // }
        // else
        // {
        // throw new IllegalArgumentException("invalid output format: " +
        // simulation_output_format);
        // }
    }

    public void mode_gui(MadhocSimulation simulation) throws Throwable
    {
        try
        {
            String themepack = simulation.getConfiguration().getString("skinlf_themepack");

            if (!themepack.equals("none"))
            {
                try
                {
                    URL url = getClass().getResource("gui/" + themepack + "themepack.zip");
                    Skin skin = SkinLookAndFeel.loadThemePack(url);
                    SkinLookAndFeel.setSkin(skin);
                    SkinLookAndFeel.enable();
                }
                catch (Throwable t)
                {
                    t.printStackTrace();
                    System.err.println("Skin Look&Feel themepack \"" + themepack + "\" cannot be installed");
                }
            }
        }
        catch (Throwable t)
        {
            t.printStackTrace();
            System.err.println("Non fatal error! Unable to set skin: " + t.getMessage());
        }

        SimulationFrame frame = new SimulationFrame(simulation);
        frame.setVisible(true);
    }

    public void writeResultFiles(MadhocSimulation simulation) throws IOException, ConfigurationException
    {
        String resultDirectoryName = simulation.getConfiguration().getString("simulation_results_directory");

        for (Projection projection : simulation.getNetwork().getProjectionMap().values())
        {
            File projectionDirectory = new File(resultDirectoryName + File.separator + projection.getName());
            projectionDirectory.mkdirs();

            for (Sensor sensor : projection.getMeasureHistoryMap().keySet())
            {
                String sensorFilename = sensor.getName() + ".dat";
                sensorFilename = sensorFilename.replace(' ', '_');
                File sensorFile = new File(projectionDirectory + File.separator + sensorFilename);
                FileOutputStream fos = new FileOutputStream(sensorFile);

                for (Object value : projection.getMeasureHistoryMap().get(sensor).getValues())
                {
                    fos.write(String.valueOf(value).getBytes());
                    fos.write(0x0A);
                }

                fos.close();
            }
        }
    }

 
}