package chiffre;

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.net.*;
/**
 *
 *
 * @author Christian Semrau
 * <a href="mailto:Christian.Semrau@student.uni-magdeburg.de">
 * Christian.Semrau@student.uni-magdeburg.de</a>
 */
public class Chiffre extends Applet implements Runnable,
ActionListener, ItemListener, ChiffreInterface{
	String chiffreType;
	int coder; // aktuell ausgewaehlter Algorithmus
	// alle Algorithmen
	ChiffreInterface[] chiffre = new ChiffreInterface[20];
	// Statistik anzeigen oder nicht
	boolean showStat;

	// Schluessel des ChiffreInterface
	int key;
	// Schluessel gesetzt
	boolean set = false;

	// Thread, der die statistische Auswertung macht
	Thread kicker;
	// Objekt, das die Statistik uebernimmt
	Statistik st;

	TextField KlarText = new TextField(40);
	TextField GeheimText = new TextField(40);
	TextField SchluesselText = new TextField(10);
	Button FilternButton = new Button("Filtern");
	Button EncodeButton = new Button("Encode");
	Button DecodeButton = new Button("Decode");
	Button StatsButton = new Button("Stats");
	Choice Algorithmus = new Choice();
	TextArea StatsOne = new TextArea(5,10);
	TextArea StatsMore = new TextArea();
	TextArea StatsGGTs = new TextArea(5,10);
/**
??:
nhiebgbnfcabivrhtzxkzbntzfejlbxvxqzcxtvbrunlkwkpvb
ocoosipyhbxpccycmbkvwmrptjknhptlnreupxipvcxxmfejlb
xvxwfuftqgzfvhjbsiincchnkvkyclxwgaivztqdjohnavvwoc
lwesnctqgibxguwkxrkftdxvwxfvcgkunlpzuizcyguzpzlbtv
xwjxfambrvrhomewtqlxbmqfmohcgxvamibsxlwxsqxvvpchbx
vsnftonrxjhvmsizpnlmkhvwzglbizvjamfiecctznrxbcclwm
vxvymdxfactvmmvantvdseiyebxzfwdpdtdlwoihxranxtwiii
jnxwgwfufptlizpycmdprbmtzxecrmxmkxnnlsmgyemmdmbrvn
llmbxvaoconqenotwiiijnxwgievaaqvljncc

Vigenere (PLANET DER AFFEN):
BPRXYK HRL EWIIZ 1. Rvrgvi Fcw vlrqn Cäjzq ddx zürw Erfvf.
Yähxzr Mai hmze Tmrrxy vr xai Närixvqgbo lih mlicoiz Jaq vshv
Wgoxieoiutvj hrboeoie. Ij auru zye hzxlg deeji drmqve, szzbl izq
Mfww zvbmlxlrh azuh, uaq Cockzv tm vuoxideqr eg vr xai Eezaew dl efhqrh.
2. Eossxh nyi Eszw uli Lvafii vvmüull, eiepiütie mzz nfdi Djree ymk
ergxrg Arvwqr. Zetr vdrrl Avlpq nadh oce eaxwvvu Mfww zvbmlxlrh, rxj
dzw Pvsnvm mo wkhmsee, qzd uzq mwpshr Rvkgpkkn. Eyfw Rijqn oqvuoh hmg
cecwiy Nsewvb szwclülk. 3. Kficvye Wvy hrv waclq Nkmjzv hmr df. Wsxpj
mgäxrl izq mnuwdii Uwai pwvjxgtee escvnv, qcw Chmfei ly olbgmzgwr, auru
qv fie hrh eegidee Mjwoh uyeüuoxhlmlkwz noluzr, gfnrlx jaq usyjhey fmtkx
bvkbvürn riexwr. 4. Ewtqvx jdi hmr hmzee pii Uwaia syj hqm Cäjzq lih
yjwvwdqn kui sbe qvn izqiy ewgie Uwaia. Hvu zelw Ewpy nmrbl uli Brfmrv
oey jcjh yidslutie, jdi ütii hue Dqmkol uy yjvvlgtee. Dl mvdrrg Lfuvar
ouvu yi zbh ecoiz rfpiioh Vjsyf rqkqgiarjvx. Ispb izq Heikggy oey aiul
hmz Rfsvzpz hepbwr lly bdmv, xrn rl fvlq Vvjeytr udi Vsrrqi zl qvioctcia,
zvulmuvf azbx. 5. Spcv zätzexvc ezlzyf jli ezfqr gyzoieyf uhv
uikbvüxacdguyf Rijqn sgw nyd Oäzak xrp vjeikjnvi fcw dlx ezfqq xylzr
Uxjvq. Dvj Rvey biun dlu Xezlqv ehu avlv jrjark mxkkwbdien. Uhv zldqxqd
rikregqdhrq Ewgpzxa imzgl vqxtujamwksmtc nh hvu Mtksoov nvdp. 6. Qitmvf
wzo epr hggy iunvf hvb lmwclürxomohvf Ewpye ehm hvp Wäwas lxx zvfyldkhr
szw myx ndiqyj dlx ezfqq Xylzr. Vejvixbv Etzof rmrxwvyrpf jaol. Xvm Aymi
yidslutx kh ymr Teedrq qm ofwgvi hhv nlvp mwdtiüavgx. Ravl pei hmvb
Rajrh lreiz bwurv Cuzi qsvlp qs atrvx edgun iioegbk iei, udi Vsrrqi
zl tscoh jhrl avvlmls emv ue hrl Zvutdüxwxyeq uzw hwyvvxqn Srjvx
kzmyhsldhr. 7. Rrmbuzq mai qyz rmol nye zvyjxvq gnu rüepnvi Nzxie
egsxwfelcwyo uutie, usk wizxyi hrl yivtdüeyxmtr Riarmwruhr, daf bkfkzq
Qswjhv bvkbvürnvi Nzxie, yeyj zfbbrihrh. Kusfzuwy nslu orcfii hqr Srjvx
az jcaiuhv vvjeytrye, qcw Chmfei ly olbgmzgwr. Amrle rzmbk? JYAP ZMD
USE YSYI WPBGR LQYEI ES QYDVGUN LREIZ!

 *
 * @param obj java.awt.event.ActionEvent
 */
public void actionPerformed(ActionEvent event) {
	Object obj = event.getSource();
	if (obj instanceof Button){
		String action = event.getActionCommand();
		if (action.equals("Filtern")){
			KlarText.setText(filter(KlarText.getText()));
			GeheimText.setText(filter(GeheimText.getText()));
		}else
		if (action.equals("Encode")){
			if (coder>0){
				chiffre[coder].setKey(SchluesselText.getText());
				GeheimText.setText(chiffre[coder].encode(KlarText.getText()));
			}
		}else
		if (action.equals("Decode")){
			if (coder>0){
				chiffre[coder].setKey(SchluesselText.getText());
				KlarText.setText(chiffre[coder].decode(GeheimText.getText()));
			}
		}
		if (action.equals("Stats")){
			if (st!=null){
				kicker = null;
			}else{
				st = new Statistik(GeheimText.getText());
				StatsOne.setText("Geduld...");
				StatsMore.setText("Geduld...");
				StatsGGTs.setText("Geduld...");
				kicker = new Thread(this);
				kicker.start();
			}
		}
	}
}
/*
 * Implementiert einen Caesar-aehnlichen Verschluesselungs-Algorithmus.
 * Es wird das Alphabet umgedreht und dann mit einem Schluessel verschoben.
*/
public String decode(String s) {
	return encode(s);
}
/*
 * Implementiert einen Caesar-aehnlichen Verschluesselungs-Algorithmus.
 * Es wird das Alphabet umgedreht und dann mit einem Schluessel verschoben.
*/
public String encode(String s) {
	int k=key;
	if (!set) return "";
	char[] geheim = new char[s.length()];
	for (int i=0; i<s.length(); i++){
		char klar = s.charAt(i);
		char code;
		if (klar>='a' && klar<='z'){
			code = (char)(('z'-klar+k)%26 +'a');
		}else
		if (klar>='A' && klar<='Z'){
			code = (char)(('Z'-klar+k)%26+'A');
		}else
			code = klar;
		geheim[i] = code;
	}
	return new String(geheim);
}

/**
 * Liefert einen String, der nur die Buchstaben (klein) von s enthaelt.
 */
public static String filter(String s) {
  String chars =
  // enthaelt alle Zeichen, die der Filter "durchlassen" soll
	"ABCDEFGHIJKLMNOPQRSTUVWXYZ"+"abcdefghijklmnopqrstuvwxyz";
  String f = "";
  char c;
  for (int i = 0; i < s.length(); )
	if (chars.indexOf(c=s.charAt(i++))>=0)
	  f += c;
  return f.toLowerCase();
}
/**
 * Returns information about this applet.
 * @return a string of information about this applet
 */
public String getAppletInfo() {
	return
		"ChiffreApplet\n" +
		"by Christian Semrau, 06.02.2000\n" + 
		"Christian.Semrau@student.uni-magdeburg.de";
}
/**
 * 
 * @param s java.lang.String
 */
public static ChiffreInterface getCoder(String s) {
	if (s==null||s.length()<=0) return null;
	if (s.equals("-")) return null;
	try{
		return (ChiffreInterface)(Class.forName(s).newInstance());
	}catch(InstantiationException e){
	}catch(ClassCastException e){
	}catch(IllegalAccessException e){
	}catch(ClassNotFoundException e){
	}
	return null;
}
/**
 * Returns parameters defined by this applet.
 * @return an array of descriptions of the receiver's parameters
 */
public java.lang.String[][] getParameterInfo() {
	String[][] info = {
		{"ChiffreTypeN", "String", "Klassen-Name des Algorithmus (N=1..20)"},
		{"Statistik","boolean","Statistik anzeigen (true/false)"+
			" [height mit: 350, ohne: 150]"}
	};
	return info;
}
/**
 * Initializes the applet.
 * 
 * @see #start
 * @see #stop
 * @see #destroy
 */
public void init() {
	super.init();

	showStat = "true".equalsIgnoreCase(getParameter("Statistik"));
	kicker = null;
	st = null;

	GridBagLayout gbl = new GridBagLayout();
	GridBagConstraints gbc;
	Label label;
	setLayout(gbl);

	// Auswahlliste
	Algorithmus.add("-");
	int alg = 1; // Nummer des naechsten "ChiffreType"-Parameters
	int ch = 1; // Anzahl der gefundenen ChiffreInterfaces
	String s;
	do{
		s = getParameter("ChiffreType"+(alg++));
		ChiffreInterface cI = getCoder(s);
		if (cI!=null){
			chiffre[ch++] = cI;
			Algorithmus.add(s);
		}
	}while (s != null || alg>=chiffre.length);
/*
	{
		s = "chiffre.ChiffreApplet";
		ChiffreInterface cI = getCoder(s);
		if (cI!=null){
			chiffre[ch++] = cI;
			Algorithmus.add(s);
		}
	}
*/
	coder = (ch>1)?1:0;

	gbc = makegbc(0,0,1,1,GridBagConstraints.HORIZONTAL);
	gbl.setConstraints(Algorithmus, gbc);
	add(Algorithmus);
	Algorithmus.select(coder);
	Algorithmus.addItemListener(this);

	// Textfelder und Buttons
	Panel pane = new Panel();
//	pane.setLayout(new GridLayout(1,3));
	pane.add(FilternButton);
	FilternButton.addActionListener(this);
	pane.add(EncodeButton);
	EncodeButton.addActionListener(this);
	pane.add(DecodeButton);
	DecodeButton.addActionListener(this);
	if (showStat){
		pane.add(StatsButton);
		StatsButton.addActionListener(this);
	}
	gbc = makegbc(1,0,1,1,GridBagConstraints.NONE);
	gbc.anchor = GridBagConstraints.WEST;
//	gbc.weightx = 100;
	gbl.setConstraints(pane, gbc);
	add(pane);

	label = new Label("Christian Semrau");
	gbc = makegbc(2,0,1,1,GridBagConstraints.NONE);
	gbc.anchor = GridBagConstraints.EAST;
	gbc.weightx = 100;
	gbl.setConstraints(label, gbc);
	add(label);

	label = new Label("Klartext:");
	gbc = makegbc(0,1,1,1,GridBagConstraints.NONE);
	gbc.anchor = GridBagConstraints.EAST;
	gbl.setConstraints(label, gbc);
	add(label);

	label = new Label("Geheimtext:");
	gbc = makegbc(0,2,1,1,GridBagConstraints.NONE);
	gbc.anchor = GridBagConstraints.EAST;
	gbl.setConstraints(label, gbc);
	add(label);

	label = new Label("Schluessel:");
	gbc = makegbc(0,3,1,1,GridBagConstraints.NONE);
	gbc.anchor = GridBagConstraints.EAST;
	gbl.setConstraints(label, gbc);
	add(label);

	gbc = makegbc(1,1,2,1,GridBagConstraints.HORIZONTAL);
	gbl.setConstraints(KlarText, gbc);
	add(KlarText);

	gbc = makegbc(1,2,2,1,GridBagConstraints.HORIZONTAL);
	gbl.setConstraints(GeheimText, gbc);
	add(GeheimText);

	gbc = makegbc(1,3,2,1,GridBagConstraints.HORIZONTAL);
	gbl.setConstraints(SchluesselText, gbc);
	add(SchluesselText);

	if (showStat){
		gbc = makegbc(0,4,1,1,GridBagConstraints.VERTICAL);
		gbl.setConstraints(StatsOne, gbc);
		add(StatsOne);

		pane = new Panel();
		pane.setLayout(new BorderLayout());
		pane.add("Center",StatsMore);
		pane.add("East",StatsGGTs);
	
		gbc = makegbc(1,4,2,1,GridBagConstraints.BOTH);
		gbc.weightx = 100;
		gbc.weighty = 100;
		gbl.setConstraints(pane, gbc);
		add(pane);
		// konfigurieren
		StatsOne.setEditable(false);
		StatsMore.setEditable(false);
		StatsGGTs.setEditable(false);
		int points = StatsMore.getFont().getSize();
		Font f = new Font("Monospaced",Font.PLAIN,points);
		StatsOne.setFont(f);
		StatsMore.setFont(f);
		StatsGGTs.setFont(f);
	}
	int points = KlarText.getFont().getSize();
	Font f = new Font("Monospaced",Font.PLAIN,points);
	KlarText.setFont(f);
	GeheimText.setFont(f);
	SchluesselText.setFont(f);
}
/**
 * 
 * @param event java.awt.event.ItemEvent
 */
public void itemStateChanged(ItemEvent event) {
	Object obj = event.getSource();
	if (obj == Algorithmus){
		coder = Algorithmus.getSelectedIndex();
		SchluesselText.setText("");
	}
}
/**
 * 
 * @return java.awt.GridBagConstraints
 * @param x int
 * @param y int
 * @param w int
 * @param h int
 */
public static GridBagConstraints makegbc(int x, int y, int w, int h, int fill) {
	GridBagConstraints gbc = new GridBagConstraints();
	gbc.gridx = x;
	gbc.gridy = y;
	gbc.gridwidth = w;
	gbc.gridheight = h;
	gbc.fill = fill;
	gbc.insets = new Insets(1, 1, 1, 1);
	return gbc;
}
/**
 * 
 */
public void run() {
	Thread me = Thread.currentThread();
	boolean finished = false;
	while(kicker == me){
		if (!st.calculate()){
			StatsOne.setText(st.getOnes());
			StatsMore.setText(st.getSorted());
			StatsGGTs.setText(st.getGGTs());
			kicker = null;
			finished = true;
		}else{
			int perc = st.percDone();
			StatsMore.setText("Geduld...\n"+perc);
			try{
				Thread.sleep(100);
			}catch(InterruptedException e){
			}
		}
	}
	st = null;
	if (!finished){
			StatsOne.setText("");
			StatsMore.setText("");
			StatsGGTs.setText("");
	}
}
/**
 * setKey method comment.
 */
public void setKey(String s) {
	if (s==null||s.length()<=0){ set = false; return; }
	if (Character.isLetter(s.charAt(0))){
		key = (Character.toLowerCase(s.charAt(0))-'a');
		set = true;
		return;
	}
	try{
		key = (new Integer(s).intValue()%26);
		set = true;
		while (key<0) key+=26;
	}catch(NumberFormatException e){
		set = false;
	}
}
/**
 * 
 */
public void start() {
	KlarText.setText("");
	String s = getParameter("Geheimtext");
	if (s==null||s.length()<=0)
		GeheimText.setText("");
	else
		GeheimText.setText(s);
	SchluesselText.setText("");
	coder = (Algorithmus.getItemCount()>0)?1:0;
	Algorithmus.select(coder);
	if (showStat){
		StatsOne.setText("");
		StatsMore.setText("");
		StatsGGTs.setText("");
	}
}
/**
 * 
 */
public void stop() {
	kicker = null;
}
}