/* 
 *    DES class
 *
 *  Written by Damir Perovic, Zagreb, Croatia.
 *  Freeware, distributed "As Is". No warranties of any kind.
 *  No part of this program is permitted for copy or use of any kind.
 *  Copyright 2000 by Damir Perovic
 */

import java.awt.*;
import java.awt.event.*;
import java.applet.*;

public class Des extends Applet implements ActionListener
{
  // DES variables
  Binary[] binK = new Binary[16];
  Binary[] binC = new Binary[16];
  Binary[] binD = new Binary[16];
  Binary[] binL = new Binary[17];
  Binary[] binR = new Binary[17];
  Binary[] binExR = new Binary[16];
  Binary[] binF = new Binary[16];


  // program control panel
  TextField texData;          // input data
  TextField texDataHEX;
  TextField texResult;        // result data
  TextField texResultHEX;
  TextField texKey;           // key
  TextField texKeyHEX;
  TextField texPause;         // pause value
  Button btnGenerateKeys;
  Button btnEncode;
  Button btnDecode;
  Button btnPause;
  Button btnSkipOne;
  Button btnSkipAll;
  Panel pnlHandle;            // last add panel to Applet

  // pause/skip
  boolean bPause = false;
  boolean bSkipOne = false;
  boolean bSkipAll = false;

  // generate keys object
  GenerateKeys CgenKey;

  // encode/decode data object
  EnDecodeData CedData;
  

/*
 *  Applet control
 */
  // initalize applet
  public void init() {
    initializeDES();
    createObjects();
  }

  // start applet
  public void start() {
    // if not active do nothing
    if (!bPause) {
      if (CgenKey != null) CgenKey.resume();
      if (CedData != null) CedData.resume();
    }
  }
  // stop applet
  public void stop() {
    // if not active do nothing
    if (!bPause) {
      if (CgenKey != null) CgenKey.suspend();
      if (CedData != null) CedData.suspend();
    }
  }

  public void destroy() {}


/*
 *  Create applet control panel
 */
  void initializeDES() {
    for (int i=0; i<16; i++) {
      binK[i] = new Binary(48);
      binC[i] = new Binary(28);
      binD[i] = new Binary(28);
      binF[i] = new Binary(32);
      binExR[i] = new Binary(16);
    }
    for (int i=0; i<17; i++) {
      binL[i] = new Binary(32);
      binR[i] = new Binary(32);
    }
  }



/*
 *  Create applet control panel
 */
  void createObjects() {
    // use flow layout for panels
    setLayout(new FlowLayout(FlowLayout.LEFT));

    // large font
    setFont(new Font(getFont().getName(), getFont().getStyle(), 14));

    // text fields
    texData = new TextField(30);
    texDataHEX = new TextField(30);
    texResult = new TextField(30);
    texResult.setEditable(false);
    texResultHEX = new TextField(30);
    texResultHEX.setEditable(false);
    texKey = new TextField(20);
    texKeyHEX = new TextField(20);
    texPause = new TextField("0.2", 5);

    // create program control panel
    Panel p, pOver, control;

    control = new Panel(new BorderLayout());
    // add labels
    p = new Panel(new GridLayout(0, 1));
    p.add(new Label("Data:", Label.RIGHT));
    p.add(new Label("Result:", Label.RIGHT));
    p.add(new Label("Key:", Label.RIGHT));
    control.add(p, BorderLayout.WEST);
    
    // add Data text field
    pOver = new Panel(new GridLayout(0, 1));
    p = new Panel(new FlowLayout());
    p.add(texData);
    p.add(texDataHEX);
    pOver.add(p);
    // add Result text field
    p = new Panel(new FlowLayout());
    p.add(texResult);
    p.add(texResultHEX);
    pOver.add(p);
    p = new Panel(new FlowLayout(FlowLayout.LEFT));
    // add Key and Pause text field
    p.add(texKey);
    p.add(texKeyHEX);
    p.add(new Label("Pause:", Label.RIGHT));
    p.add(texPause);
    pOver.add(p);
    control.add(pOver, BorderLayout.CENTER);
    add(control);

    // buttons
    btnGenerateKeys = new Button("  Generate keys  ");
    btnGenerateKeys.addActionListener(this);
    btnEncode = new Button("  Encode data  ");
    btnEncode.addActionListener(this);
    btnDecode = new Button("  Decode data  ");
    btnDecode.addActionListener(this);
    btnPause = new Button("  Pause  ");
    btnPause.setEnabled(false);
    btnPause.addActionListener(this);
    btnSkipOne = new Button("  Skip one  ");
    btnSkipOne.setEnabled(false);
    btnSkipOne.addActionListener(this);
    btnSkipAll = new Button("  Skip all  ");
    btnSkipAll.setEnabled(false);
    btnSkipAll.addActionListener(this);

    control = new Panel(new GridLayout(0, 1));
    p = new Panel(new FlowLayout(FlowLayout.CENTER, 10, 15));
    p.add(btnGenerateKeys);
    p.add(btnEncode);
    p.add(btnDecode);
    p.add(btnPause);
    p.add(btnSkipOne);
    p.add(btnSkipAll);
    control.add(p);
    add(control);
  }



/*
 *  Actions
 */
  public void actionPerformed(ActionEvent e) {
    Button b = (Button) e.getSource();

    // generate keys
    if (b == btnGenerateKeys) {
      generateKeys();
    // encode data
    } else if (b == btnEncode) {
      endecodeData(EncodeData.encode);
    // decode data
    } else if (b == btnDecode) {
      endecodeData(EncodeData.decode);
    }

    // skip one
    if (b == btnSkipOne) {
      setSkipOne(true);
    }
    // skip all
    if (b == btnSkipAll) {
      setSkipAll(true);
    }

    // pause
    if (b == btnPause) {
      // continue execution
      if (bPause) {
        bPause = false;
        btnPause.setLabel("  Pause  ");
        if (CgenKey != null) CgenKey.resume();
        if (CedData != null) CedData.resume();
      // pause execution
      } else {
        bPause = true;
        btnPause.setLabel("  Continue  ");
        if (CgenKey != null) CgenKey.suspend();
        if (CedData != null) CedData.suspend();
      }
    }

  }

  // Generate Keys
  void generateKeys() {
    // get key value
    Binary data = new Binary(64);
    // text value
    if (texKey.getText().length() != 0) {
      data.set(texKey.getText());
      texKeyHEX.setText(toHexString(texKey.getText()));
    // hex value
    } else {
      data.setHexString(texKeyHEX.getText());
    }

    CgenKey = new GenerateKeys(this, data);
    CgenKey.start();
  }

  // Encode/Decode Data
  void endecodeData(byte type) {
    // get key value
    Binary data = new Binary(64);
    // text value
    if (texData.getText().length() != 0) {
      data.set(texData.getText());
      texDataHEX.setText(toHexString(texData.getText()));
    // hex value
    } else {
      data.setHexString(texDataHEX.getText());
    }

    CedData = new EnDecodeData(this, type, data);
    CedData.start();
  }


/*
 *  Control buttons
 */
  // hide buttons
  void hideButtons() {
    btnGenerateKeys.setEnabled(false);
    btnEncode.setEnabled(false);
    btnDecode.setEnabled(false);
    btnPause.setEnabled(true);
    btnSkipOne.setEnabled(true);
    btnSkipAll.setEnabled(true);
   }

  // show buttons
  void showButtons() {
    btnGenerateKeys.setEnabled(true);
    btnEncode.setEnabled(true);
    btnDecode.setEnabled(true);
    btnPause.setEnabled(false);
    btnSkipOne.setEnabled(false);
    btnSkipAll.setEnabled(false);
  }



/*
 *  Synchronized variables
 */
  // set skip one
  synchronized void setSkipOne(boolean value) {
    bSkipOne = value;
  }
  // set skip one
  synchronized void setSkipAll(boolean value) {
    bSkipAll = value;
  }


/*
 *  Support
 */
  // convert string to hex string
  public static String toHexString(String value) {
    char[] ch = value.toCharArray();

    String result = "";
    for (int i=0; i<ch.length; i++) {
      result += Integer.toHexString(ch[i]);
    }
    return result;
  }

  // get pause value
  public long getPause() {
    // if not skip one and not skip all
    if (!bSkipOne && !bSkipAll) {
      // wait some time
      try {
        return (long) (Float.valueOf(texPause.getText()).floatValue() * 1000);
      } catch (NumberFormatException e) {
        return 0;
      }
    // skip
    } else {
      return 0;
    }
  }
}
