//Kedar Hirve taught me how to use Graphic User Interface(GUI).

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class PlagueSimulator extends JApplet {
    private static final int FRAME_WIDTH = 520;
    private static final int FRAME_HEIGHT = 590;
    public static final int GRID_SIDE = 50;
    public static final int GRID_SIZE = GRID_SIDE * GRID_SIDE;

    public static double plagueStrength = .5;
    public static int lifespan = 5;
    public static double fitness = 10.0;

    public static int population = 100;
    public static double perc_immune = .1;
    public static double perc_infected = .1;

    public static int totalCount = 0;
    public static int immuneCount = 0;
    public static int infectedCount = 0;
    public static int carrierCount = 0;
    public static int nonImmuneCount = 0;
    public static int deadCount = 0;


    static PlagueOptionsFrame jfOptions;
    static PlaguePopulationFrame jfPopulate;
    static JFrame jfCounts;
    static JTextField jtStrength, jtLifespan, jtFitness,
               jtNonImmune, jtImmune, jtCarrier, jtInfected, jtTotal;
    static JLabel lbStrength, lbLifespan, lbFitness,
               lbNonImmune, lbImmune, lbCarrier, lbInfected, lbTotal,
               lbImmuneCount, lbCarrierCount, lbInfectedCount, lbNonImmuneCount,
               lbDeadCount, lbTotalCount;
    static JButton btSet, btPopulate, btClear;
    static Grid grid;
    static Simulator ca;

    final static int GRID_ROWS = 50;
    final static int GRID_COLUMNS = 50;

    public PlagueSimulator () {
	System.err.println ("Creating plague simulator...");
	JRootPane pane = getRootPane ();
	//@assume pane != null
	pane.putClientProperty ("defaultSystemEventQueueCheck", Boolean.TRUE);
	System.err.println ("Okay");
    }

    public void init() {
	System.err.println ("Init");
	grid = new Grid (GRID_SIDE, GRID_SIDE);
       	ca = new Simulator (FRAME_HEIGHT, FRAME_WIDTH, grid);
        //@assume ca != null
	Container content = getContentPane ();

        jfOptions = new PlagueOptionsFrame("Plague Simulator Options");
        jfPopulate = new PlaguePopulationFrame("Plague Simulator Auto-populator");
        jfCounts = new JFrame("Plague Victim Counts");

        jtStrength = new JTextField(String.valueOf(plagueStrength), 5);
        jtLifespan = new JTextField(String.valueOf(lifespan), 5);
        jtFitness = new JTextField(String.valueOf(fitness), 5);
        jtTotal = new JTextField(String.valueOf(population),5);
        jtImmune = new JTextField(String.valueOf(perc_immune * 100), 5);
        jtInfected = new JTextField(String.valueOf(perc_immune * 100), 5);

        lbStrength = new JLabel("Plague Strength");
        lbLifespan = new JLabel("Lifespan");
        lbFitness = new JLabel("Fitness");
        lbTotal = new JLabel("Population Size");
        lbImmune = new JLabel("% Immune");
        lbInfected = new JLabel("% Infected");

        lbImmuneCount = new JLabel();
        lbImmuneCount.setForeground(Color.yellow);
        lbCarrierCount = new JLabel();
        lbCarrierCount.setForeground(Color.green);
        lbInfectedCount = new JLabel("Infected Count: " + infectedCount);
        lbInfectedCount.setForeground(Color.red);
        lbNonImmuneCount = new JLabel("NonImmune Count: " + nonImmuneCount);
        lbNonImmuneCount.setForeground(Color.orange);
        lbDeadCount = new JLabel("Dead Count: " + deadCount);
        lbDeadCount.setForeground(Color.gray);
        lbTotalCount = new JLabel("Total Count: " + totalCount);

        setImmuneCount(0);
        setCarrierCount(0);
        setInfectedCount(0);
        setNonImmuneCount(0);
        setDeadCount(0);
        setTotalCount(0);

        btSet = new JButton("Set");
        btPopulate = new JButton("Populate");
        btClear = new JButton("Clear");

        btSet.addActionListener(jfOptions);
        btPopulate.addActionListener(jfPopulate);
        btClear.addActionListener(jfPopulate);

        Container jfc = jfOptions.getContentPane();
        //@assume jfc != null
        jfc.setLayout(new GridLayout(4, 2));
        jfc.add(lbStrength);
        jfc.add(jtStrength);
        jfc.add(lbLifespan);
        jfc.add(jtLifespan);
        jfc.add(lbFitness);
        jfc.add(jtFitness);
        jfc.add(new JPanel());
        jfc.add(btSet);

        jfc = jfPopulate.getContentPane();
        //@assume jfc != null
        jfc.setLayout(new GridLayout(4, 2));
        jfc.add(lbTotal);
        jfc.add(jtTotal);
        jfc.add(lbImmune);
        jfc.add(jtImmune);
        jfc.add(lbInfected);
        jfc.add(jtInfected);
        jfc.add(btPopulate);
        jfc.add(btClear);

        jfc = jfCounts.getContentPane();
        //@assume jfc != null
        jfc.setLayout(new FlowLayout());
        jfc.add(lbTotalCount);
        jfc.add(lbDeadCount);
        jfc.add(lbNonImmuneCount);
        jfc.add(lbImmuneCount);
        jfc.add(lbInfectedCount);
        jfc.add(lbCarrierCount);


        jfOptions.setSize(200,200);
        jfOptions.setLocation(520,200);
        jfPopulate.setSize(200,200);
        jfPopulate.setLocation(520,390);
        jfCounts.setSize(720, 80);
        jfCounts.setLocation(0, 590);

        jfOptions.show();
        jfPopulate.show();
        jfCounts.show();

	// Add classes to the simulation.
	ca.addClass ("ImmuneWalker");
        ca.addClass ("NonImmuneWalker");
        ca.addClass ("CarrierWalker");
        ca.addClass ("InfectedWalker");

	if (content != null) {
	    content.add (ca, BorderLayout.CENTER);
	} else {
	    System.err.println ("ERROR: No content pane");
	}
    }

    public static void populateGrid (int total, double imm, double inf) {
       double typeChance, infectedChance;
       int randomRow, randomCol;
       SimObject current;
       //@assume grid != null
       PlagueSimulator.setTotalCount(PlagueSimulator.totalCount + total);
       while (total > 0) {
         do {
           randomRow = (int)(grid.numRows() * Math.random());
           randomCol = (int)(grid.numColumns() * Math.random());
         } while (! grid.isSquareEmpty(randomRow, randomCol));

         total--;

         typeChance = Math.random();
         infectedChance = Math.random();
         if (typeChance <= imm) {
           if (infectedChance <= inf) {
             current = new CarrierWalker();
           }
           else {
             current = new ImmuneWalker();
           }
         }
         else {
           if (infectedChance <= inf) {
             current = new InfectedWalker();
           }
           else {
             current = new NonImmuneWalker();
           }
         }
         grid.setObjectAt(randomRow, randomCol, current);
       }
    }

  static void setImmuneCount(int a) {
     immuneCount = a;
     //@assume lbImmuneCount != null
     lbImmuneCount.setText("Immune Count: " + immuneCount);
  }
  static void setCarrierCount(int a) {
     carrierCount = a;
     //@assume lbCarrierCount != null
     lbCarrierCount.setText("Carrier Count: " + carrierCount);
  }
  static void setNonImmuneCount(int a) {
     nonImmuneCount = a;
     //@assume lbNonImmuneCount != null
     lbNonImmuneCount.setText("NonImmune Count: " + nonImmuneCount);
  }
  static void setInfectedCount(int a) {
     infectedCount = a;
     //@assume lbInfectedCount != null
     lbInfectedCount.setText("Infected Count: " + infectedCount);
  }
  static void setDeadCount(int a) {
     deadCount = a;
     //@assume lbDeadCount != null
     lbDeadCount.setText("Dead Count: " + deadCount);
  }
  static void setTotalCount(int a) {
     totalCount = a;
     //@assume lbTotalCount != null
     lbTotalCount.setText("Total Count: " + totalCount);
  }
}

class PlagueOptionsFrame extends JFrame implements ActionListener {
  public PlagueOptionsFrame(String s) {
    super(s);
  }

  public void actionPerformed(ActionEvent ae) {
     //@assume ae != null
     if (ae.getSource() == PlagueSimulator.btSet) {
       try {
         //@assume PlagueSimulator.jtStrength != null
         PlagueSimulator.plagueStrength = Math.abs(Double.parseDouble(PlagueSimulator.jtStrength.getText()));//@nowarn NonNull//Default value
      } catch (NumberFormatException nfe) { }

       try {
         //@assume PlagueSimulator.jtLifespan != null
         PlagueSimulator.lifespan = Math.abs(Integer.parseInt(PlagueSimulator.jtLifespan.getText()));//@nowarn NonNull//Default value
       } catch (NumberFormatException nfe) { }

       try {
         //@assume PlagueSimulator.jtFitness != null
         PlagueSimulator.fitness = Math.abs(Double.parseDouble(PlagueSimulator.jtFitness.getText()));//@nowarn NonNull//Default value
       } catch (NumberFormatException nfe) { }
     }
  }
}

class PlaguePopulationFrame extends JFrame implements ActionListener {
  public PlaguePopulationFrame(String s) {
    super(s);
  }

  public void actionPerformed(ActionEvent ae) {
     int pop;
     double imm;
     double inf;
     //@assume ae != null

     if (ae.getSource() == PlagueSimulator.btPopulate) {
       try {
        //@assume PlagueSimulator.jtTotal != null
         pop = Math.abs(Integer.parseInt(PlagueSimulator.jtTotal.getText()));//@nowarn NonNull//Default value
       } catch (NumberFormatException nfe) { pop = PlagueSimulator.population; }

       try {
         //@assume PlagueSimulator.jtImmune != null
         imm = Double.parseDouble(PlagueSimulator.jtImmune.getText());//@nowarn NonNull//Default value
       } catch (NumberFormatException nfe) { imm = PlagueSimulator.perc_immune; }
       if (imm > 100) {
          imm = 100;
       }
       imm /= 100;

       try {
         //@assume PlagueSimulator.jtInfected != null
         inf = Double.parseDouble(PlagueSimulator.jtInfected.getText());//@nowarn NonNull//Default value
       } catch (NumberFormatException nfe) { inf = PlagueSimulator.perc_infected; }
       if (inf > 100) {
          inf = 100;
       }
       inf /= 100;
       PlagueSimulator.populateGrid(pop, imm, inf);
     }
     else if (ae.getSource() == PlagueSimulator.btClear) {
        //@assume PlagueSimulator.grid != null
        PlagueSimulator.grid.clearGrid();
        PlagueSimulator.setImmuneCount(0);
        PlagueSimulator.setCarrierCount(0);
        PlagueSimulator.setInfectedCount(0);
        PlagueSimulator.setNonImmuneCount(0);
        PlagueSimulator.setDeadCount(0);
        PlagueSimulator.setTotalCount(0);
     }
     //@assume PlagueSimulator.ca != null
     PlagueSimulator.ca.repaint();
  }

}