/* 
   An object belonging to the Coder can encode and decode characters
   based on a "key word" that is provided in its constructor.
   Each character in a message is "offset" by some integer amount.  For
   example, if 'a' is offset by 5, the result is 'f'.  Characters at the
   end of the alphabet wrap around to the beginning.  For example, if
   'x' is offset by 5, the result is 'c'.  Different characters in a
   message are offset by different amounts, and the amounts are specified
   by the letters in the key word.  (If a Coder object is used to
   encode or decode more than one message, you should call reset() before
   beginning each new message to make sure that the first offset is
   used for the first character in the message.)
*/


public class Coder {

   private int[] offsets;  // Character offsets, obtained from key word.
   private int pos = 0;    // Index in array offsets of next offset to be
                           //   used in the encoding/decoding of a message.


   public Coder(String keyWord) {
         // Create a Coder object that can encode/decode messages
         // using the specified keyword.  Only LETTERS in keyWord
         // are significant; other characters are ignored.
      keyWord = keyWord.toLowerCase();
      int letterCt = 0;
      for (int i = 0; i < keyWord.length(); i++)
         if (keyWord.charAt(i) >= 'a' && keyWord.charAt(i) <= 'z')
            letterCt++;
      offsets = new int[letterCt];
      letterCt = 0;
      for (int i = 0; i < keyWord.length(); i++) {
         char ch = keyWord.charAt(i);
         if (ch >= 'a' && ch <= 'z') {
            offsets[letterCt] = (int)ch - (int)'a' + 1;
            letterCt++;
         }
      }
   }


   public void reset() {
        // Call this to reset the offsets before starting a new message.
      pos = 0;
   }


   public char encode(char ch) {
        // Encode a single character.
      if (ch >= 'a' && ch <= 'z') {
         int n = (int)ch;
         n += offsets[pos];
         if (n > 'z')
            n -= 26;
         ch = (char)n;
         pos++;
         if (pos >= offsets.length)
            pos = 0;
      }
      else if (ch >= 'A' && ch <= 'Z') {
         int n = (int)ch;
         n += offsets[pos];
         if (n > 'Z')
            n -= 26;
         ch = (char)n;
         pos++;
         if (pos >= offsets.length)
            pos = 0;
      }
      return ch;
   }


   public char decode(char ch) {
         // Decode a single comment.
      if (ch >= 'a' && ch <= 'z') {
         int n = (int)ch;
         n -= offsets[pos];
         if (n < 'a')
            n += 26;
         ch = (char)n;
         pos++;
         if (pos >= offsets.length)
            pos = 0;
      }
      else if (ch >= 'A' && ch <= 'Z') {
         int n = (int)ch;
         n -= offsets[pos];
         if (n < 'A')
            n += 26;
         ch = (char)n;
         pos++;
         if (pos >= offsets.length)
            pos = 0;
      }
      return ch;
   }

 
   public String encode(String clearText) {
        // Encode an entire String.
      StringBuffer codedText = new StringBuffer(clearText.length());
      for (int i = 0; i < clearText.length(); i++) {
         codedText.append(encode(clearText.charAt(i)));
      }
      return codedText.toString();
   }

 
   public String decode(String codedText) {
         // Decode an entire String.
      StringBuffer clearText = new StringBuffer(codedText.length());
      for (int i = 0; i < codedText.length(); i++) {
         clearText.append(decode(codedText.charAt(i)));
      }
      return clearText.toString();
   }

} // end of class Coder.