/* 
 * DisplayPanel.java
 *
 * by Kwan Hoi Ching Eddie
 * 
 * last revised: 06/06/1996
 *
 */

import java.awt.*;
import java.applet.*;
import java.lang.*;
import java.util.*;

/* display panel at the middle of display. */
public class DisplayPanel extends Panel {

  int cell_num;

  String curr_name;
  int curr_d, curr_s1, curr_s2, curr_t;
  ControlBar control;
  Random rand;
  Color bg_color, fg_color;

  Message message;

  boolean posSet;

  Cell cell[];
  Cell currCell;
  int width, height;
  int cell_width, cell_height;

  /* return the number of cells in the display. */
  private int CellNum() {

    if (curr_d == 1)
      return curr_s1;
    else 
      return curr_s1 * curr_s2;
  }

  /* return the index of the cell inside the array by (x,y). */
  private int cellIndexXY(int x, int y) {

    Cell c;

    for (int i = 0; i < cell_num; i++) {
 
      c = cell[i];

      if (x > c.getxPos() && x < c.getxPos()+cell_width &&
          y > c.getyPos() && y < c.getyPos()+cell_height) 
        return i;

    }
   
    return -1;
  }

  /* return the index of the cell inside the array by column and row. */
  private int cellIndexCR(int column, int row) {

    Cell c;
    int x, y;

    x = row*cell_width + firstCell().getxPos();
    y = column*cell_height + firstCell().getyPos();

    for (int i = 0; i < cell_num; i++) {
 
      c = cell[i];

      if (x == c.getxPos() && y == c.getyPos()) 
        return i;
    }

    return -1;
  }

  /* return the the column index of the cell. */
  private int columnElement(Cell c) {

    int yf, yc;

    yf = firstCell().getyPos();
    yc = c.getyPos();

    return (yc - yf) / cell_height;
  }
 
  /* return the the row index of the cell. */
  private int rowElement(Cell c) {

    int xf, xc;

    xf = firstCell().getxPos();
    xc = c.getxPos();

    return (xc - xf) / cell_width;
  }
 
  /* return the cell having index 1. */
  private Cell firstCell() {

    int xLeast = Integer.MAX_VALUE;
    int yLeast = Integer.MAX_VALUE;
    int pos = -1;
    
    for (int i = 0; i < cell_num; i++) {

      if (cell[i].getxPos() <= xLeast && cell[i].getyPos() <= yLeast) {
        xLeast = cell[i].getxPos();
        yLeast = cell[i].getyPos();
        pos = i;
      }
    }

    return cell[pos];
  }

  /* create new cells. */
  private void CellCreate() {

    cell = new Cell[cell_num];

    for (int i = 0; i < cell_num; i++) 

      cell[i] = new Cell(cell_width, cell_height, curr_t, rand);

  }

  // constructor.
  public DisplayPanel(int dim, int s1, int s2, int type) {
   
    bg_color = new Color(200, 200, 0);
    fg_color = new Color(0, 100, 0);

    cell_width = 35;
    cell_height = 25;

    rand = new Random();

    curr_name = "A";
    curr_d = dim;
    curr_s1 = s1;
    curr_s2 = s2;
    curr_t = type;

    posSet = false;
    cell_num = CellNum();
    CellCreate();
  }

  /* return the current selected cell. */
  public Cell getCurrCell() {

    return currCell;

  }

  /* return the totol number of cell in display. */
  public int getCellNum() {

    return cell_num;

  }

  /* return the name of the array. */
  public String getName() {

    return curr_name;

  }

  /* return the dimension of the array. */
  public int getDim() {

    return curr_d;

  }

  /* return the size of the array. */
  public int getSize(int which) {

    switch (which) {
      case 1:
        return curr_s1;
      case 2:
        return curr_s2;
      default:
        return -1;
    }
  }

  /* capture the user's mouse position and action. */
  public boolean mouseDown(Event e, int x, int y) {

    int index;
    Graphics g;

    g = getGraphics();

    if ((index = cellIndexXY(x, y)) != -1) {

      currCell.unselect();
      currCell.paint(g, currCell.getxPos(), currCell.getyPos());
      currCell = cell[index];
      currCell.select();
      currCell.paint(g, currCell.getxPos(), currCell.getyPos());

      // repaint message.
      repaint(20, height-40, width-40, 50);
    }

    return true;
  }
 
  /* change the name of the array. */
  public void NameChange(String n) {

    if (!curr_name.equals(n)) {
 
      curr_name = n;
      repaint();
    }

  }

  /* change the dimension of the array. */
  public void DimensionChange(int d) {

      if (curr_d != d) {

        curr_d = d;
        cell_num = CellNum();
        CellCreate();
        posSet = false;
        repaint();
      }
  }

  /* change the size of the array. */
  public void SizeChange(int which, int s) {

    switch (which) {
      case 1:
        if (curr_s1 != s) {
          curr_s1 = s;
          cell_num = CellNum();
          CellCreate();
          repaint();
        }
        break;
      case 2:
        if (curr_s2 != s) {
          curr_s2 = s;
          cell_num = CellNum();
          CellCreate();
          repaint();
        }
        break;
      default:
        break;
    }
    posSet = false;
  }

  /* change the data of the array. */
  public void TypeChange(int t) {

    if (curr_t != t) {
     
      curr_t = t;
      CellCreate();
      posSet = false;
      repaint();
    }
  }

  /* modify the value in the element. */
  private void valueModify(int index, String str) {

    Cell c;
    Graphics g;

    c = cell[index];
    g = getGraphics();

    currCell.unselect();
    currCell.paint(g, currCell.getxPos(), currCell.getyPos());

    for (int i = 0; i < 60; i++) {

      c.select();
      c.paint(g, c.getxPos(), c.getyPos());

      for (int j = 0; j < 5000; j++);

      c.unselect();
      c.paint(g, c.getxPos(), c.getyPos());

      for (int j = 0; j < 5000; j++);

    }

    c.setValue(str);
    c.select();
    c.paint(g, c.getxPos(), c.getyPos());

    currCell = c;
  }

  /* doing assignment manipulation. */
  public void Assignment(ElementInfo e) {
 
    int i1, i2;
    String value;
    Graphics g;

    g = getGraphics();

    // case for value assignment.
    if (!e.value.equals("")) {
      //case for one dimensional array
      if (e.dim == 1) 
        i1 = cellIndexCR(0, e.row1);
      
      //case for two dimensional array
      else 
        i1 = cellIndexCR(e.column1, e.row1);

      valueModify(i1, e.value);

    // case for array element assignment.
    } else {
      //case for one dimensional array
      if (e.dim == 1) {
        i1 = cellIndexCR(0, e.row1);
        i2 = cellIndexCR(0, e.row2);
        
      //case for two dimensional array
      } else {
        i1 = cellIndexCR(e.column1, e.row1);
        i2 = cellIndexCR(e.column2, e.row2);
      }

      cell[i2].refer();
      cell[i2].paint(g, cell[i2].getxPos(), cell[i2].getyPos());
      valueModify(i1, cell[i2].getValue());
      cell[i2].unrefer();
      cell[i2].paint(g, cell[i2].getxPos(), cell[i2].getyPos());

    }
    // repaint message.
    repaint(20, height-40, width-40, 50);
  }

  /* paint the array on the display. */
  public void paint(Graphics g) {

    int offset = 4;
    int i;
    int j = curr_s1;

    width = size().width;
    height = size().height;

    int centre_x = width / 2 - 50; 
    int centre_y = height / 2 - 50;

    int curr_x = centre_x;
    int curr_y = centre_y;

    int counter1 = 0; 
    int counter2 = 0;

    g.setColor(bg_color);
    g.fill3DRect(0, offset, width-1, height-2*offset, true);

    for (i = 0; i < cell_num; i++) {

      cell[i].setPos(curr_x, curr_y);

      if (--j > 0) {
        curr_x = (int) (curr_x + (cell_width*(counter1+1)*Math.pow(-1, counter1++)));
      } else {
        j = curr_s1;
        counter1= 0;
        curr_x = centre_x;
        curr_y = (int) (curr_y + (cell_height*(counter2+1)*Math.pow(-1, counter2++)));
      }
    }

    if (posSet == false) {
      posSet = true;
      currCell = firstCell();
    }

    currCell.select();

    for (i = 0; i < cell_num; i++) {

      cell[i].paint(g, cell[i].getxPos(), cell[i].getyPos());

      if (curr_d == 2 && rowElement(cell[i]) == 0) {
        g.drawString(Integer.toString(columnElement(cell[i])), cell[i].getxPos()-15, cell[i].getyPos()+15);
      }
      if (columnElement(cell[i]) == 0) {
        g.drawString(Integer.toString(rowElement(cell[i])), cell[i].getxPos()+12, cell[i].getyPos()-8);
      }
    }

    switch (curr_d) {
      case 1:
        message = new Message(this, rowElement(currCell), -1);
        break;
      case 2:
        message = new Message(this, rowElement(currCell), columnElement(currCell));
        break;
      default:
        break;
    }

    /* refresh the message box. */
    message.paint(g, width-10, height-10);
  }

}


