
// Vigenere.java
// Andrew Davison, ad@coe.psu.ac.th, April 2023

/* The Vigenère cipher is a natural extension of the 
   Caesar cipher (Caesar.java). Instead of shifting every
   letter in the plaintext by the same amount, the offset
   is dictated by the length of the current letter in a 
   secret key.

   As each letter is encrypted in the plaintext, a letter is
   taken from the key, and translated into an offset which is
   applied to the plaintext letter. When all the letters in the
   key have been used once, the key is reused.

   https://en.wikipedia.org/wiki/Vigen%C3%A8re_cipher

   Usage:
     > compile Vigenere.java
     > run Vigenere  <message> <key>
    e.g.
     > run Vigenere Andrew dog
*/


public class Vigenere
{

  public static void main(String[] args)
  {
    if (args.length != 2) {
      System.out.println("Usage: run Vigenere <message> <key>");
      return;
    }
    System.out.println("Message: \"" + args[0] + "\"");
    System.out.println("Key: \"" + args[1] + "\"");

    String cipher = encode(args[0], args[1]);
    System.out.println("Encrypted message : \"" + cipher + "\"");

    String decipher = decode(cipher, args[1]);
    System.out.println("Decrypted message : \"" + decipher + "\"");
  } /* main */



  public static String encode(String msg, String key)
  {
    StringBuilder sb = new StringBuilder();
    int j = 0;

    for (int i = 0; i < msg.length(); i++) {
      char ch = msg.charAt(i);
      if (Character.isUpperCase(ch)) {
        int shift = (key.toUpperCase().charAt(j) - 'A') % 26;
        ch += shift;
        sb.append((char) (ch > 'Z' ? ch - 26 : ch));         
      }
      else if (Character.isLowerCase(ch)) {
        int shift = (key.toLowerCase().charAt(j) - 'a') % 26;
        ch += shift;
        sb.append((char) (ch > 'z' ? ch - 26 : ch));         
      }
      else
        sb.append(ch);
      j = (j+1) % key.length();
    }
    return sb.toString();
  } /* encode */


  public static String decode(String msg, String key)
  {
    StringBuilder sb = new StringBuilder();
    int j = 0;

    for (int i = 0; i < msg.length(); i++) {
      char ch = msg.charAt(i);
      if (Character.isUpperCase(ch)) {
        int shift = (key.toUpperCase().charAt(j) - 'A') % 26;
        ch -= shift;
        sb.append((char) (ch < 'A' ? ch + 26 : ch)); 
      }
      else if (Character.isLowerCase(ch)) {
        int shift = (key.toLowerCase().charAt(j) - 'a') % 26;
        ch -= shift;
        sb.append((char) (ch < 'a' ? ch + 26 : ch)); 
      }
      else
        sb.append(ch);
      j = (j+1) % key.length();
    }
    return sb.toString();
  } /* decode */


}  // end of Vigenere class
