/**
 * File: SubstitutionAnalysis.java
 * @author A.Kurd <alan.kurd@trincoll.edu>
 * 
 * Description: Implements a Java 1.1 version of a GUI tool for the final ouput of this program.  It displays
*  the most likely key, listed 'a' to 'z', the number of bigram hits (matches) and trigram hits.
 * Credits: This program is modelled after the frequency test of the CryptoToolJ program by Ralph Morelli.
 *
 * Copyright: This program is in the public domain. You can do whatever you want with
 *  it as long as I get credit for my work and as long as you offer your changes to me
 *  so I can possible add them to the "official" version.
 */
package analyzers;             // Analyzer plugins belong to this package

import hcrypto.analyzer.*;     // This is where Analyzer is
import java.awt.TextArea;
import hcrypto.cipher.*;
import java.awt.*;
import java.awt.event.*;   
import java.util.*;
import java.lang.*;

public class SubstitutionAnalysis extends Frame implements Analyzer{

   public  Frame  frame[] = new Frame[10];     //the frames that the top 10 KeyGroups are displayed
   public  KeyBuilder kb= new KeyBuilder();   //to count letter frequency
   public Calculate ct = new Calculate();         //to score the different KeyGroups
   public  BigramCount bc= new BigramCount();	//to collect Bigram data
   public TrigramCount tc = new TrigramCount();	//to collect Trigram data
   public KeyGroups kg = new KeyGroups();	//to create possible KeyGroups
   public  String output [] = new String [10];		//The 10 strings were the output is collected
   public int result [] = new int[128];	//array to collect the order of letters for the KeyGroup
   public int TriFreq[][] = new int[128][3];	//used to store the Trigram by frequency because originally stoared as chars and need ints
   public int resultKey [] = new int[128];	//Final Key stored in the array
   public int random1[] = {1,2,3,4,5,6,7,8};	//numbers to create the key for groups 2 thru 5
   public int random2[] = {1,2};
   public int random3[] = {1,2,3,4,5,6,7,8,9};
   public int random4[] = {1,2,3};
   private TextArea text1;     // Pointers to the text to be analyzed
   private TextArea display1;  // And the window where results are displayed
   public TextArea display [] = new TextArea[10];	//TextAreas for displaying the keys
   public char  freqI [] = {'e','t', 'a', 'o', 'i', 'n', 's', 'h', 'r', 'd', 'l', 'c', 'u', 'm', 'w', 'f', 'g', 'y', 'p', 'b','v', 'k', 'j', 'x', 'q', 'z'};//list of letters by frequency
   public int total [] = new int [10];	//scores for the KeyGroup
   public int rating [][] = new int [10][3];	//ratings for the Keys
      int l = 0;

   public  void SubstitutionAnalysis(String text){ }//BigramDisplay

//necessary for the analysis package

   public void setup(TextArea text1, TextArea display1) { 
      this.text1 = text1;
      this.display1 = display1;
   }//setup

/*First method called by the class.  Tells the user they have called this method. Collects data on letter frequency, bigram frequency
   and trigram frequency.  Changes the chars for Trigram data into ints, rather than chars for use later.  This recreates the keys
    the possible keys and rescores them.  It then finds the highest scoring key and displays it for the user.*/

   public void run() {
      display1.append("Substitution Analysis activated" + "\n");
      int n = 1;
      kb.count(text1.getText());
      bc.count(text1.getText());
      tc.count(text1.getText());
      for(int i=0; i<12; i++)
          if(tc.frequencies[i] != null){
              TriFreq[i][0] = (int)tc.frequencies[i][0];
              TriFreq[i][1] = (int)tc.frequencies[i][1];
              TriFreq[i][2] = (int)tc.frequencies[i][2];}//if
      for( int i = 0; i<10; i++){
         create(i);
         score(i,result);}//for
      int k = total[0];
      for(int j = 1; j<10; j++){
           if(k<total[j]) {k = total[j]; l = j;}//if
      }//for
      result = create(l);
      build(result);
      probable(rating);
   }//run

/*This method finds the "candidate" key that has the greatest number of bigram and trigram matches.  It then displays
   all the information for the user with the letters listed 'a' to 'z'.*/

   public void probable(int r [][]){
       int greatest = r[0][0];
       int biHits = r[0][1];
       int triHits = r[0][2];
       int position = 0;
       for(int i=1;i<10;i++){
           if(r[i][0] > greatest){ greatest = r[i][0]; biHits = r[i][1]; triHits = r[i][2]; position = i;}//if
       }//for
       display1.append("Value: " + greatest + " for Key" + (position+1) + " with " + biHits + " bigram hits and " + triHits + " trigram hits.\n");
       display1.append("The most accurate key, listed from a to z, is: \n");
       int high = rating[0][0];
       int place = 0;
       for(int i=1; i<10; i++)
           if(rating[i][0] !=0)
               if(rating[i][0]>high){high=rating[i][0]; place=i;}//if
       create(1);
       createKey(result, place);
       //build(result);
       display1.append((char)resultKey[2]+ "" + ", " +(char)resultKey[19]+ "" + ", " +(char)resultKey[11]+ "" + ", " +(char)resultKey[9]+ "" + ", " +
        (char)resultKey[0]+ "" + ", " +(char)resultKey[15]+ "" + ", " +(char)resultKey[16]+ "" + ", " +(char)resultKey[7]+ "" + ", " +(char)resultKey[4]+ "" + ", " +
        (char)resultKey[22]+ "" + ", " +(char)resultKey[21]+ "" + ", " +(char)resultKey[10]+ "" + ", " +(char)resultKey[13]+ "" + ", " +(char)resultKey[5]+ "" + ", " +
        (char)resultKey[3]+ "" + ", " +(char)resultKey[18]+ "" + ", " +(char)resultKey[24]+ "" + ", " +(char)resultKey[8]+ "" + ", " +(char)resultKey[6]+ "" + ", " +
        (char)resultKey[1]+ "" + ", " +(char)resultKey[12]+ "" + ", " +(char)resultKey[20]+ "" + ", " +(char)resultKey[14]+ "" + ", " +(char)resultKey[23]+ "" + ", " +
        (char)resultKey[17]+ "" + ", " +(char)resultKey[25]+ "" + "\n");
   }//probable

/*This method creates the possible KeyGroups and the scores them below*/

   public int[] create(int i){
      if(i == 0){
         for(int k = 0; k<kb.tabulate.length; k++)
            result [k] = kb.tabulate[k][1];}//if
      else{
         result[0] = kb.tabulate[i][1];
         result[i] = kb.tabulate[0][1];
         for(int k = 1; k<kb.tabulate.length; k++)
            if (k == i) result[k] = result[k];
            else result[k] = kb.tabulate[k][1]; }//else
      return result;
   }//create

   public void score (int j, int []res){
     total[j] = ct.accumulate(res, bc.tabulate, 0);
     
   }//score

/*This method creates 9 possible "candidate" keys.*/

   public void build (int [] res){
        for( int i = 0; i<9; i++){
             createKey(res,i);
             rate(i);
        }//for
   }//res
   
/*this method actually shuffles the letters in the array to create the different keys shifting letter by groups of the KeyGroup*/

   public int [] createKey(int [] res, int count){
        resultKey[0] = res [0];
        for(int i = 0; i<8; i++) resultKey[i+1] = res[((random1[i]+count)%8)+1];
        for(int i = 0; i<2; i++) resultKey[i+9] = res[((random2[i]+count)%2)+9];
        for(int i = 0; i<9; i++) resultKey[i+11] = res[((random3[i]+count)%9)+11];
        for(int i = 0; i<3; i++) resultKey[i+20] = res[((random4[i]+count)%3)+20];
        for(int i = 0; i<3; i++) resultKey[i+23] = res[((random4[i]+count)%3)+23];
        return resultKey;
   }//createKey

/*this method scores the different keys by comparing them to the bigram and trigram data collected on the cipher text.  Each time
  a match is found, the score of the key is incremented accordingly*/

   public int [][] rate(int r){
     for(int i=0; i<30; i++){
        if(resultKey[1] == bc.tabulate[i][1] && resultKey[7]==bc.tabulate[i][2]) {rating[r][0] = rating[r][0] + 30-i; rating[r][1]++;}
        else if(resultKey[7] == bc.tabulate[i][1] && resultKey[0]==bc.tabulate[i][2]) {rating[r][0] = rating[r][0] + 29-i; rating[r][1]++;}
        else if(resultKey[4] == bc.tabulate[i][1] && resultKey[5]==bc.tabulate[i][2]) {rating[r][0] = rating[r][0] + 28-i; rating[r][1]++;}
        else if(resultKey[0] == bc.tabulate[i][1] && resultKey[8]==bc.tabulate[i][2]) {rating[r][0] = rating[r][0] + 27-i; rating[r][1]++;}
        else if(resultKey[2] == bc.tabulate[i][1] && resultKey[5]==bc.tabulate[i][2]) {rating[r][0] = rating[r][0] + 26-i; rating[r][1]++;}
        else if(resultKey[8] == bc.tabulate[i][1] && resultKey[0]==bc.tabulate[i][2]) {rating[r][0] = rating[r][0] + 25-i; rating[r][1]++;}
        else if(resultKey[0] == bc.tabulate[i][1] && resultKey[9]==bc.tabulate[i][2]) {rating[r][0] = rating[r][0] + 24-i; rating[r][1]++;}
        else if(resultKey[3] == bc.tabulate[i][1] && resultKey[5]==bc.tabulate[i][2]) {rating[r][0] = rating[r][0] + 23-i; rating[r][1]++;}
        else if(resultKey[0] == bc.tabulate[i][1] && resultKey[6]==bc.tabulate[i][2]) {rating[r][0] = rating[r][0] + 22-i; rating[r][1]++;}
        else if(resultKey[6] == bc.tabulate[i][1] && resultKey[1]==bc.tabulate[i][2]) {rating[r][0] = rating[r][0] + 21-i; rating[r][1]++;}
        else if(resultKey[0] == bc.tabulate[i][1] && resultKey[5]==bc.tabulate[i][2]) {rating[r][0] = rating[r][0] + 20-i; rating[r][1]++;}
        else if(resultKey[2] == bc.tabulate[i][1] && resultKey[1]==bc.tabulate[i][2]) {rating[r][0] = rating[r][0] + 19-i; rating[r][1]++;}
        else if(resultKey[1] == bc.tabulate[i][1] && resultKey[3]==bc.tabulate[i][2]) {rating[r][0] = rating[r][0] + 18-i; rating[r][1]++;}
        else if(resultKey[5] == bc.tabulate[i][1] && resultKey[1]==bc.tabulate[i][2]) {rating[r][0] = rating[r][0] + 17-i; rating[r][1]++;}
        else if(resultKey[7] == bc.tabulate[i][1] && resultKey[2]==bc.tabulate[i][2]) {rating[r][0] = rating[r][0] + 16-i; rating[r][1]++;}
        else if(resultKey[5] == bc.tabulate[i][1] && resultKey[9]==bc.tabulate[i][2]) {rating[r][0] = rating[r][0] + 15-i; rating[r][1]++;}
        else if(resultKey[3] == bc.tabulate[i][1] && resultKey[12]==bc.tabulate[i][2]) {rating[r][0] = rating[r][0] + 14-i; rating[r][1]++;}
        else if(resultKey[0] == bc.tabulate[i][1] && resultKey[2]==bc.tabulate[i][2]) {rating[r][0] = rating[r][0] + 13-i; rating[r][1]++;}
        else if(resultKey[5] == bc.tabulate[i][1] && resultKey[16]==bc.tabulate[i][2]) {rating[r][0] = rating[r][0] + 12-i; rating[r][1]++;}
        else if(resultKey[2] == bc.tabulate[i][1] && resultKey[6]==bc.tabulate[i][2]) {rating[r][0] = rating[r][0] + 11-i; rating[r][1]++;}
        else if(resultKey[3] == bc.tabulate[i][1] && resultKey[8]==bc.tabulate[i][2]) {rating[r][0] = rating[r][0] + 10-i; rating[r][1]++;}
        else if(resultKey[1] == bc.tabulate[i][1] && resultKey[4]==bc.tabulate[i][2]) {rating[r][0] = rating[r][0] + 9-i; rating[r][1]++;}
        else if(resultKey[4] == bc.tabulate[i][1] && resultKey[6]==bc.tabulate[i][2]) {rating[r][0] = rating[r][0] + 8-i; rating[r][1]++;}
        else if(resultKey[0] == bc.tabulate[i][1] && resultKey[1]==bc.tabulate[i][2]) {rating[r][0] = rating[r][0] + 7-i; rating[r][1]++;}
        else if(resultKey[4] == bc.tabulate[i][1] && resultKey[1]==bc.tabulate[i][2]) {rating[r][0] = rating[r][0] + 6-i; rating[r][1]++;}
        else if(resultKey[2] == bc.tabulate[i][1] && resultKey[8]==bc.tabulate[i][2]) {rating[r][0] = rating[r][0] + 5-i; rating[r][1]++;}
        else if(resultKey[1] == bc.tabulate[i][1] && resultKey[0]==bc.tabulate[i][2]) {rating[r][0] = rating[r][0] + 4-i; rating[r][1]++;}
        else if(resultKey[6] == bc.tabulate[i][1] && resultKey[0]==bc.tabulate[i][2]) {rating[r][0] = rating[r][0] + 3-i; rating[r][1]++;}
        else if(resultKey[7] == bc.tabulate[i][1] && resultKey[4]==bc.tabulate[i][2]) {rating[r][0] = rating[r][0] + 2-i; rating[r][1]++;}
        else if(resultKey[3] == bc.tabulate[i][1] && resultKey[15]==bc.tabulate[i][2]) {rating[r][0] = rating[r][0] + 1-i; rating[r][1]++;}}//for
   for(int j=0;j<12;j++){
        if(resultKey[1] == TriFreq[j][0] && resultKey[7]==TriFreq[j][1] && resultKey[0]==TriFreq[j][2]) {rating[r][0] = rating[r][0] + 84-j; rating[r][2]++;}//the
        else if(resultKey[4] == TriFreq[j][0] && resultKey[5]==TriFreq[j][1] && resultKey[16]==TriFreq[j][2]) {rating[r][0] = rating[r][0] + 41-j; rating[r][2]++;}//ing
        else if(resultKey[2] == TriFreq[j][0] && resultKey[5]==TriFreq[j][1] && resultKey[9]==TriFreq[j][2]) {rating[r][0] = rating[r][0] + 40-j; rating[r][2]++;}//and
        else if(resultKey[7] == TriFreq[j][0] && resultKey[0]==TriFreq[j][1] && resultKey[9]==TriFreq[j][2]) {rating[r][0] = rating[r][0] + 39-j; rating[r][2]++;}//her
        else if(resultKey[0] == TriFreq[j][0] && resultKey[8]==TriFreq[j][1] && resultKey[0]==TriFreq[j][2]) {rating[r][0] = rating[r][0] + 38-j; rating[r][2]++;}//ere
        else if(resultKey[0] == TriFreq[j][0] && resultKey[5]==TriFreq[j][1] && resultKey[1]==TriFreq[j][2]) {rating[r][0] = rating[r][0] + 37-j; rating[r][2]++;}//ent
        else if(resultKey[1] == TriFreq[j][0] && resultKey[7]==TriFreq[j][1] && resultKey[2]==TriFreq[j][2]) {rating[r][0] = rating[r][0] + 36-j; rating[r][2]++;}//tha
        else if(resultKey[5] == TriFreq[j][0] && resultKey[1]==TriFreq[j][1] && resultKey[7]==TriFreq[j][2]) {rating[r][0] = rating[r][0] + 35-j; rating[r][2]++;}//nth
        else if(resultKey[14] == TriFreq[j][0] && resultKey[2]==TriFreq[j][1] && resultKey[6]==TriFreq[j][2]) {rating[r][0] = rating[r][0] + 34-j; rating[r][2]++;}//was
        else if(resultKey[0] == TriFreq[j][0] && resultKey[1]==TriFreq[j][1] && resultKey[7]==TriFreq[j][2]) {rating[r][0] = rating[r][0] + 33-j; rating[r][2]++;}//eth
        else if(resultKey[15] == TriFreq[j][0] && resultKey[3]==TriFreq[j][1] && resultKey[8]==TriFreq[j][2]) {rating[r][0] = rating[r][0] + 32-j; rating[r][2]++;}//for
        else if(resultKey[9] == TriFreq[j][0] && resultKey[1]==TriFreq[j][1] && resultKey[7]==TriFreq[j][2]) {rating[r][0] = rating[r][0] + 31-j; rating[r][2]++;}//dth
     }//for
        return rating;
   }//rate()
}//SubstitutionAnalysis Class