/* -*- Mode: c++ -*-
 * @(#) KeyPad.java 1.0 6/10/97 Ralph Morelli
 *
 * Classes: KeyPad Canvas
 * Author: Ralph Morelli, Trinity College (ralph.morelli@trincoll.edu)
 * 
 * Copyright (c) 1996 Ralph Morelli. All Rights Reserved.
 *
 * Permission to use, copy, modify, and distribute this software
 * and its documentation for NON-COMMERCIAL purposes and
 * without fee is hereby granted provided that this copyright
 * notice appears in all copies. 
 */

import java.awt.*;

class KeyPad extends Canvas {
  CryptoGramTool theApplet;			// pointer to the applet
  CryptoGram cryptogram;				// the cryptogram itself
  boolean firstMouseDown;
															// COLOR SCHEME
  final static Color appletbGround = new Color(110,110,155); // new Color(100,30,255); 
  final static Color 
    textColor = Color.darkGray,			
  buttonbGround = Color.white,
  hintColor = Color.white,
  buttonFocusColor = new Color(110,110,155), //Color.darkGray,	
  labelColor = Color.blue;
    					
															// REFERENCE CONSTANTS
  
  final static int kBlockWidth = 30, kBlockHeight = 30, kBlocksWide =13, kBlocksHigh =2;		
  final static int kTopKey 	= 5,	kLeftKey 	= 20;
  final static int hintL = 5, hintT = 100, hintW = 425, hintH = 150;
  final static int newL = 70, newT = 70, newW = 50, newH = 15;
  final static int resetL = 150, resetT = 70, resetW = 50, resetH = 15;
  final static int hintBL = 230, hintBT = 70, hintBW = 60, hintBH = 15;
  final static int makeKeyL = 310, makeKeyT = 70, makeKeyW = 50, makeKeyH = 15;
  final static int kAppWidth 	= 40 + (kBlockWidth * kBlocksWide);			// 430
  final static int kAppHeight = 3 * (kBlockHeight * kBlocksHigh + 30);	// 270
  
  final static Font bigFont = new Font("TimesRoman",0,18); 
  final static Font regularFont = new Font("TimesRoman", 0, 12);
  final static Font hintFont = new Font("TimesRoman", 0, 10);
    
  int gCurX	= 0;			// current mouse locations in terms of block number
    int	gCurY	= 0;
  boolean hintON = false;	       // hints are off initially
  boolean makeKeyON = false;	      // make a key is off initially
	
  public KeyPad (CryptoGramTool a) {  // CONSTRUCTOR
    firstMouseDown = true;
    theApplet = a;
    cryptogram = new CryptoGram( );	  		
  } // keyPad Constructor
	
  private void reset() {
    firstMouseDown = true;
    gCurX = 0;
    gCurY = 0;
    repaint();
  }
	
  public void paint(Graphics g) {
    													// REFERENCE VARIABLES
    int left = 0;	int right = kAppWidth - 1;
    int top = 0;	int bottom = kAppHeight - 1;
    int tempLeft = 0;	int tempRight = 0;           int tempTop = 0;
    int viewWidth;		int viewHeight;
    int buttonWidth = 0;	int buttonHeight = 0;
    int buttonLeft = 0;	        int buttonTop = 0;
    int tileLeft;		int tileTop;
	
    g.draw3DRect(0,0,kAppWidth,kAppHeight,true);		// Paint background
    g.setColor(appletbGround);					// fill outer rectangle
    g.fillRect(0+1,0+1,kAppWidth-1,kAppHeight-1);
    
    g.setColor(buttonFocusColor);				// fill outer rectangle
    paintKeyPad(g);
    
    g.setColor(buttonbGround);					// fill outer rectangle
    g.drawLine(kLeftKey,90,430 - kLeftKey,90);
    
    paintButton(g,newL,newT,newW,newH,"ResetAll");		// paint reset key button    
    paintButton(g,resetL,resetT,resetW,resetH,"ResetKey");	// paint reset button    
    paintButton(g,hintBL,hintBT,hintBW,hintBH,"ToggleHint");	// paint hint button    
    paintButton(g,makeKeyL,makeKeyT,makeKeyW,makeKeyH,"MakeKey"); // paint makekey button    
    paintHint(g);   	        	
  } // paint

    /*----------------------------------------------*/
       
   private void paintButton (Graphics g, int left, int top, int width, int height, String s) {
      g.setColor(buttonbGround);  
      g.draw3DRect(left-1,top-1,width,height,true);
      g.fillRect(left+1,top+1,width-2,height-2);			// Paint the  button
      g.setColor(labelColor);
   	  g.drawString(s,left+2, top + 11);
    }

   private void paintButtonClicked (Graphics g, int left, int top, int width, int height, String s) {
      g.setColor(labelColor);
      g.draw3DRect(left-1,top-1,width,height,true);
      g.fillRect(left+1,top+1,width-2,height-2);			// Paint the  button
      g.setColor(buttonbGround);  
      g.drawString(s,left+2, top + 11);
    }
    
  private void paintKeyPad(Graphics g) {
    gCurX = 0;
    gCurY = 0;
    for (int j = 0 ; j < kBlocksHigh ; j++) 			// draw the keymap
      for (int i = 0 ; i < kBlocksWide ; i++) {
	PaintCell(g,i,j);
      } // for i
  }
	
  private void PaintCell(Graphics g, int x, int y) {  // x is col, y is row 
    g.setFont(regularFont);
    int tempLeft = kLeftKey + (x * kBlockWidth);	// Compute coordinates
    int tempTop = kTopKey + (y * kBlockHeight);
    
    if (InActiveBlock(x,y))						// Set Cell's color
      g.setColor(buttonFocusColor);
    else
      g.setColor(buttonbGround);
    
    g.fillRect(tempLeft+1, tempTop+1, kBlockWidth-1, kBlockHeight-1);	// Paint cell
    g.setColor(appletbGround);		
    g.draw3DRect(tempLeft,tempTop,kBlockWidth, kBlockHeight,true);
      
    Character chobj = new Character( getCellLabel(x,y) );			// Draw cell's label
    g.setColor(labelColor);
    g.drawString(chobj.toString(), tempLeft + 2, tempTop + 11);	
      
    g.setColor(textColor);						       			// Draw cell's letter
    chobj = new Character( getCellContents(x,y) );
    g.drawString(chobj.toString(), tempLeft + 12, tempTop + 20);				
  } // PaintCell
    
  private void paintHint(Graphics g) {
    Color tempColor = g.getColor();
    g.setColor(appletbGround);
    g.fillRect(hintL,hintT,hintW, hintH);
    if (hintON) {
      g.setColor(hintColor);
      g.setFont(regularFont);
      g.drawString( cryptogram.getHint(), hintL+2, hintT+11);
      g.setColor(tempColor);
    }
    else {
      g.setColor(tempColor);
    }
  }

  private void makeKey(Graphics g) {
    makeKeyON = !makeKeyON;
    if (makeKeyON) {
      cryptogram.initKey();
      paintKeyPad(g);
      g.setFont(regularFont);
      Color tempColor = g.getColor();
      g.setColor(appletbGround);
      g.fillRect(hintL,hintT,hintW, hintH);
      g.setColor(buttonbGround);
      g.drawString( "Type a KEYWORD with no repeating letters into the first few ", hintL, hintT+11);
      g.drawString( "cells of the keypad -- i.e., from 'A'.. -- and then press", hintL, hintT+26);
      g.drawString( "the MakeKey button again.", hintL, hintT+41);
      g.setColor(tempColor);
    }
    else {
      String keyString = cryptogram.generateKey();
      paintKeyPad(g);
      Color tempColor = g.getColor();
      
      g.setColor(appletbGround);
      g.fillRect(hintL,hintT,hintW, hintH);
      g.setColor(buttonbGround);
      //  g.drawString( "The KEYWORD is " + keyString, hintL, hintT+11);
      theApplet.setDisplay( cryptogram.getCipherText() +"\n\n"+ cryptogram.getPlainText() ) ;
      g.setColor(tempColor);
    }
  }


  private char getCellLabel(int x, int y) {
    return((char) ((int)'A' + getCellNum(x,y)) );	// and return the corresponding letter	
  }
 
  private char getCellContents(int x, int y) {			// x is col y is the row
    return( cryptogram.getPlainCh( getCellNum(x,y) ));	// and return its key
  }	

  private int getCellNum(int x, int y) {
    return x + 13 * y;
  }


  public boolean handleEvent(Event evt) {
    
    				// The cryptoText is read on the first event.
    if (evt.id == evt.MOUSE_DOWN || evt.id == evt.KEY_PRESS || evt.id == evt.KEY_ACTION)
      if ( firstMouseDown ) {
	cryptogram.setCipherText( theApplet.getCipherText() ) ;
	firstMouseDown = false;
      }
      	
    switch(evt.id) {
         case evt.MOUSE_DOWN: mouseDown(evt.x,evt.y);          return(true);
	 case evt.MOUSE_UP:   mouseUp(evt.x,evt.y);            return(true);
	 case evt.KEY_PRESS:  keyDown(evt.key, gCurX,gCurY);   return(true);
	 case evt.KEY_ACTION: moveFocus(evt.key, gCurX,gCurY); return(true);
	 default: return super.handleEvent(evt);
    }
  } // handleEvent


  private boolean InActiveBlock(int x, int y) {
    if (x == gCurX && y == gCurY)
      return(true);
    return(false);
  } // InActiveBlock

  private void setActiveBlock(int x, int y) {
    gCurX	= x;		// reset current mouse locations
    gCurY	= y;
  } //setActiveBlock

  public void mouseDown(int x, int y) {
           
    requestFocus();
      
    if ( buttonPressed(x,y) ) return;
      								// WAS THE RESET BUTTON CLICKED
    if (x < kLeftKey)			// return if the click was not in the key area		
      return;					
    if (y < kTopKey)
      return;
      
    int j = y - kTopKey;		// get row and column indexes of the block
    j /= kBlockHeight;
    
    int i = x - kLeftKey;
    i /= kBlockWidth;
      
    if (i >= 0 && i < kBlocksWide && j >= 0 && j < kBlocksHigh) {
      if (!InActiveBlock(i,j)) { 
	int old_i = gCurX, old_j = gCurY;
	setActiveBlock(i, j);
	PaintCell(getGraphics(), i,j);
	PaintCell(getGraphics(), old_i,old_j);
	paintHint(getGraphics());
      } 
      return;
    }
  }
    
  private boolean buttonPressed(int x, int y) {
    // RESET BUTTON
    if (x >= newL && x <= newL+newW && y >= newT && y <= newT+newH){ 
      //  paintButtonClicked (getGraphics(), newL,newT, newW, newH, "ResetAll");   		
      theApplet.reset();
      cryptogram.reset();
      this.reset();
      return true;
    }
													// RESET KEY BUTTON    		
    if (x >= resetL && x <= resetL+resetW && y >= resetT && y <= resetT+resetH){ 
      cryptogram.initKey();
      repaint();
      theApplet.setDisplay( cryptogram.getCipherText() +"\n\n"+ cryptogram.getPlainText() ) ;	
      return true;
    }
													// HINT BUTTON
    if (x >= hintBL && x <= hintBL+hintBW && y >= hintBT && y <= hintBT+hintBH){ 
      hintON = !hintON;
      paintHint(getGraphics());
      return true;
    }
      	
    if (x >= makeKeyL && x <= makeKeyL+makeKeyW && y >= makeKeyT && y <= makeKeyT+makeKeyH){ 
      makeKey(getGraphics());
      return true;
    }
    return false;
    
    }

  public void mouseUp(int x, int y) {
    requestFocus();
  }

  
  public void keyDown(int key, int x, int y) {
     
    if (key >= 'A' && key <= 'Z')
      key = key + 32;							// convert to lower case
    
    if (cryptogram.isValidKey( key )) {
      int m = x + 13 * y;						// Use x and y to find what key this is
      cryptogram.setKeyChar( m, key );		// and store the lower case version of letter
      PaintCell(getGraphics(), x, y);
      if (!makeKeyON) { 
	paintHint(getGraphics());
	theApplet.setDisplay( cryptogram.getCipherText() +"\n\n"+ cryptogram.getPlainText() ) ;
      }	
      return;
    } //if valid
  } // keyDown
    
  private void moveFocus (int key, int x, int y ) {	// x is column, y is row
    int oldx = x, oldy = y;
    int m = getCellNum(x,y);						// cells are numbered 0..25
    // 	System.out.println("col " + x + " row " + y + " cell " + m );
    switch (key) {
    	case Event.UP: {
	  if (m >= 13 && m <= 25) { y--; } break;
	}
    	case Event.DOWN: {
	  if (m >= 0 && m <= 12) { y++; } break;
	}
    	case Event.LEFT: {
	  if ( (m > 0 && m <= 12) || (m > 13 && m <= 25) ) { x--; }
	  if (m == 0) { x = 12; y = 1;}
	  if (m == 13) { x = 12; y = 0; }
	  break;
	}
    	case Event.RIGHT: {
	  if ( (m >= 0 && m < 12) || (m >= 13 && m < 25) ) { x++; }
	  if (m == 12) { x = 0; y = 1; }
	  if (m == 25) { x = 0; y = 0; }
	  break;
	}
     } // switch
    setActiveBlock(x,y);
    PaintCell(getGraphics(), x,y);
    PaintCell(getGraphics(), oldx,oldy);
    if (!makeKeyON) paintHint(getGraphics());
  } 

 } // keyPad Canvas

