
#import "RuleControl.h"
#import "RuleType.h"
#import "random.h"
#import "Opponent.h"

@implementation RuleControl

Rule ruleMatrix[5][5];

int row, col, operatorRow, operatorCol, operandRow, operandCol;
char statusMsg[128];
int lr, ruleActive;

- init
{
  [self resetStandard:self];

  return self;
}

- resetStandard:sender
{
  int x,y;
  
  // set Globals:
  lr = 1; // blue button title "right <--> left"
  ruleActive = 0; // no rule is active
  
  for (y=0; y<5; y++) // runs top-->down
  for (x=0; x<5; x++) // from left to right
  {
    ruleMatrix[x][y].buttonX = x;
    ruleMatrix[x][y].buttonY = y;
    if ((y*5+x) < 12) // upper half
    {
      ruleMatrix[x][y].actsOn = 0; // left color
    } 
    
    if ((y*5+x) == 12) // center
    {
      ruleMatrix[x][y].actsOn = -1; // itself
    }
    
    if ((y*5+x) > 12) // lower half
    {
      ruleMatrix[x][y].actsOn = 1; // right color
    } 
  }
  
  ruleMatrix[0][0].leftColor = 0;
  ruleMatrix[0][0].rightColor = 1;

  ruleMatrix[1][0].leftColor = 0;
  ruleMatrix[1][0].rightColor = 2;

  ruleMatrix[2][0].leftColor = 0;
  ruleMatrix[2][0].rightColor = 3;

  ruleMatrix[3][0].leftColor = 1;
  ruleMatrix[3][0].rightColor = 0;

  ruleMatrix[4][0].leftColor = 1;
  ruleMatrix[4][0].rightColor = 2;

  ruleMatrix[0][1].leftColor = 1;
  ruleMatrix[0][1].rightColor = 3;

  ruleMatrix[1][1].leftColor = 2;
  ruleMatrix[1][1].rightColor = 0;

  ruleMatrix[2][1].leftColor = 2;
  ruleMatrix[2][1].rightColor = 1;

  ruleMatrix[3][1].leftColor = 2;
  ruleMatrix[3][1].rightColor = 3;

  ruleMatrix[4][1].leftColor = 3;
  ruleMatrix[4][1].rightColor = 0;

  ruleMatrix[0][2].leftColor = 3;
  ruleMatrix[0][2].rightColor = 1;

  ruleMatrix[1][2].leftColor = 3;
  ruleMatrix[1][2].rightColor = 2;

  ruleMatrix[2][2].leftColor = 4;
  ruleMatrix[2][2].rightColor = 4;

  ruleMatrix[3][2].leftColor = 3;
  ruleMatrix[3][2].rightColor = 2;

  ruleMatrix[4][2].leftColor = 3;
  ruleMatrix[4][2].rightColor = 1;

  ruleMatrix[0][3].leftColor = 3;
  ruleMatrix[0][3].rightColor = 0;

  ruleMatrix[1][3].leftColor = 2;
  ruleMatrix[1][3].rightColor = 3;

  ruleMatrix[2][3].leftColor = 2;
  ruleMatrix[2][3].rightColor = 1;

  ruleMatrix[3][3].leftColor = 2;
  ruleMatrix[3][3].rightColor = 0;

  ruleMatrix[4][3].leftColor = 1;
  ruleMatrix[4][3].rightColor = 3;

  ruleMatrix[0][4].leftColor = 1;
  ruleMatrix[0][4].rightColor = 2;

  ruleMatrix[1][4].leftColor = 1;
  ruleMatrix[1][4].rightColor = 0;

  ruleMatrix[2][4].leftColor = 0;
  ruleMatrix[2][4].rightColor = 3;

  ruleMatrix[3][4].leftColor = 0;
  ruleMatrix[3][4].rightColor = 2;

  ruleMatrix[4][4].leftColor = 0;
  ruleMatrix[4][4].rightColor = 1;

  [self setAllButtons:self];
  
  return self;
}


- resetRandom:sender
{
  int x,y;
  
  // set Globals:
  lr = 1; // blue button title "right <--> left"
  ruleActive = 0; // no rule is active
  
  for (y=0; y<5; y++) // runs top-->down
  for (x=0; x<5; x++) // from left to right
  {
    ruleMatrix[x][y].buttonX = x;
    ruleMatrix[x][y].buttonY = y;
    
    ruleMatrix[x][y].actsOn 
      = (int) floor(randomVal(0.0, 1.99999999999999)); // left/right
    ruleMatrix[x][y].leftColor 
      = (int) floor(randomVal(0.0, 3.99999999999999)); 
    ruleMatrix[x][y].rightColor 
      = (int) floor(randomVal(0.0, 3.99999999999999));
  }
  
  // center always blue
  ruleMatrix[2][2].actsOn = -1; // itself
  ruleMatrix[2][2].leftColor = 4; // blue
  ruleMatrix[2][2].rightColor = 4; // blue
  
  [self setAllButtons:self];
  
  return self;
}


- receiveClick:sender
{
  row = [buttonMatrix selectedRow];
  col = [buttonMatrix selectedCol];
  if (!ruleActive) // activate rule
  {
    ruleActive = 1;
    operatorRow = row;
    operatorCol = col;
    sprintf(statusMsg, "rule [%d, %d] activated", row, col);
  }
  else // execute rule
  {
    operandRow = row;
    operandCol = col;
    sprintf(statusMsg, "rule [%d, %d] was applied to rule [%d, %d]", 
      operatorRow, operatorCol, operandRow, operandCol);
      
    // change 
    if (ruleMatrix[operatorCol][operatorRow].actsOn == 0) // left color
    {
      // correct application of rule?
      if ( ruleMatrix[operatorCol][operatorRow].leftColor 
        == ruleMatrix[operandCol][operandRow].leftColor)
      {
        ruleMatrix[operandCol][operandRow].leftColor
	= ruleMatrix[operatorCol][operatorRow].rightColor;
        [self setIcon:operandRow:operandCol]; // the change
	[opponent move:self];
      }
      else
      {	
         NXRunAlertPanel([NXApp appName], 
         "rule [%d, %d] is not applicable", "OK", NULL, NULL, 
	 operatorCol, operatorRow);
         sprintf(statusMsg, "rule [%d, %d] was NOT applied to rule [%d, %d]", 
           operatorRow, operatorCol, operandRow, operandCol);
      }
    } 
     
    if (ruleMatrix[operatorCol][operatorRow].actsOn == 1) // right color
    {
      // correct application of rule?
      if ( ruleMatrix[operatorCol][operatorRow].leftColor 
        == ruleMatrix[operandCol][operandRow].rightColor)
      {
        ruleMatrix[operandCol][operandRow].rightColor
	= ruleMatrix[operatorCol][operatorRow].rightColor; 
        [self setIcon:operandRow:operandCol]; // the change
	[opponent move:self];
      }
      else
      {	
         NXRunAlertPanel([NXApp appName], 
         "rule [%d, %d] is not applicable", "OK", NULL, NULL, 
	 operatorCol, operatorRow);
         sprintf(statusMsg, "rule [%d, %d] was NOT applied to rule [%d, %d]", 
           operatorRow, operatorCol, operandRow, operandCol);
      }
    } 
 
    if (ruleMatrix[operatorCol][operatorRow].actsOn == -1) // side change
    {
      if (ruleMatrix[operandCol][operandRow].actsOn != -1) // not blue button
        ruleMatrix[operandCol][operandRow].actsOn 
	= 1 - ruleMatrix[operandCol][operandRow].actsOn;
        [self setText:operandRow:operandCol]; // the change
	[opponent move:self];
    }

    [buttonMatrix setState:0 at:operatorRow:operatorCol];
    [buttonMatrix setState:0 at:operandRow:operandCol];
    ruleActive = 0;
  }
  [statusLine setStringValue:statusMsg];
  return self;
}


- setIcon:(int)r:(int)c
{
  int nr;
  id button;
  
  nr = 4*ruleMatrix[c][r].leftColor + ruleMatrix[c][r].rightColor;
  switch (nr)
  {
    case 0:
      // bb
      button = [buttonMatrix cellAt:r:c];
      [button setIcon:"bb"];
      break;
    case 1:
      // bw
      button = [buttonMatrix cellAt:r:c];
      [button setIcon:"bw"];
      break;
    case 2:
      // by
      button = [buttonMatrix cellAt:r:c];
      [button setIcon:"by"];
      break;
    case 3:
      // br
      button = [buttonMatrix cellAt:r:c];
      [button setIcon:"br"];
      break;
    case 4:
      // wb
      button = [buttonMatrix cellAt:r:c];
      [button setIcon:"wb"];
      break;
    case 5:
      // ww
      button = [buttonMatrix cellAt:r:c];
      [button setIcon:"ww"];
      break;
    case 6:
      // wy
      button = [buttonMatrix cellAt:r:c];
      [button setIcon:"wy"];
      break;
    case 7:
      // wr
      button = [buttonMatrix cellAt:r:c];
      [button setIcon:"wr"];
      break;
    case 8:
      // yb
      button = [buttonMatrix cellAt:r:c];
      [button setIcon:"yb"];
      break;
    case 9:
      // yw
      button = [buttonMatrix cellAt:r:c];
      [button setIcon:"yw"];
      break;
    case 10:
      // yy
      button = [buttonMatrix cellAt:r:c];
      [button setIcon:"yy"];
      break;
    case 11:
      // yr
      button = [buttonMatrix cellAt:r:c];
      [button setIcon:"yr"];
      break;
    case 12:
      // rb
      button = [buttonMatrix cellAt:r:c];
      [button setIcon:"rb"];
      break;
    case 13:
      // rw
      button = [buttonMatrix cellAt:r:c];
      [button setIcon:"rw"];
      break;
    case 14:
      // ry
      button = [buttonMatrix cellAt:r:c];
      [button setIcon:"ry"];
      break;
    case 15:
      // rr
      button = [buttonMatrix cellAt:r:c];
      [button setIcon:"rr"];
      break;
    case 20:
      // blue
      button = [buttonMatrix cellAt:r:c];
      [button setIcon:"blue"];
      break;
  }
  return self;
}


- setText:(int)r:(int)c
{
  id button;
  
  button = [buttonMatrix cellAt:r:c];
  
  if (ruleMatrix[c][r].actsOn == -1) // the blue button
  {
    switch (lr)
    { 
      default:
      case 0:
        [button setTitle:"left <--> right"];
	lr = 1;
	break;
      case 1:
        [button setTitle:"right <--> left"];
	lr = 0;
	break;
    }
    return self;
  }
  
  if (ruleMatrix[c][r].actsOn == 0) {
    [button setTitle:"left"]; }
  else {
    [button setTitle:"right"]; }
    
  
  return self;
}


- setAllButtons:sender
{
  int x,y;
  
  // set Icons
  for (y=0; y<5; y++) // runs top-->down
  for (x=0; x<5; x++) // from left to right
  {
    [self setIcon:y:x];
    [self setText:y:x];
  }

  return self;
}


- (Rule) ruleAt:(int)x:(int)y
{
  return ruleMatrix[x][y];
} 


- setRule:(Rule)rl
{
  int x = rl.buttonX, y = rl.buttonY;
  
  ruleMatrix[x][y].leftColor = rl.leftColor;
  ruleMatrix[x][y].rightColor = rl.rightColor;
  ruleMatrix[x][y].actsOn = rl.actsOn;
    
  [self setAllButtons:self];
  return self;
}


@end
