/*
 * 2004 Utah High School Programming Contest, University of Utah
 * Take-Home Problem
 *
 * RotationCipher.java
 *
 * This file contains the implementation of the RotationCipher class.
 */

/**
 * A RotationCipher implements a particular letter rotation algorithm.  For
 * example, a RotationCipher might rotate every letter forward by one position,
 * mapping 'A' to 'B', 'B' to 'C', ..., and 'Z' to 'A'.  The rotation wraps
 * around at the end of the alphabet.  The distance of the rotation is
 * determined when the RotationCipher object is created.  There are 26 possible
 * rotation algorithms (including the shift-by-zero algorithm).
 *
 * RotationCipher implements the Cipher interface.  RotationCiphers are created
 * by the Search class.
 */
class RotationCipher implements Cipher {
    /**
     * The array that describes the translations of lowercase letters.  Array
     * index 0 corresponds to 'a', 1 to 'b', and so on.  The value of an array
     * element is the translation of the letter that corresponds to that
     * element's index.  For example, the value of `lowercaseMap[0]' is the
     * translation of `a'.
     */
    private final char lowercaseMap[] = new char[26];
    
    /**
     * The array that describes the translations of uppercase letters.  Array
     * index 0 corresponds to 'A', 1 to 'B', and so on.  The value of an array
     * element is the translation of the letter that corresponds to that
     * element's index.  For example, the value of `uppercaseMap[0]' is the
     * translation of `A'.
     */
    private final char uppercaseMap[] = new char[26];
    
    /**
     * Construct a RotationCipher object to implement a particular letter
     * rotation algorithm.  The argument to this method represents the
     * "distance" of the rotation for decryption.  For example, a distance of
     * one means that 'A' decrypts to 'B', 'B' to 'C', ..., and 'Z' decrypts to
     * 'A'.  (The rotation wraps around at the end of the alphabet.)  Letter
     * case is preserved.  Only upper- and lowercase letters are translated;
     * all other characters "decrypt" to themselves.
     *
     * @param decipherDistance    the "distance" of the letter rotation
     */
    RotationCipher(int decipherDistance) {
        char toLChar, toUChar;
        
        decipherDistance = decipherDistance % 26;
        toLChar = 'a';
        toUChar = 'A';
        for (int i = decipherDistance; i < 26; ++i) {
            this.lowercaseMap[i] = toLChar;
            this.uppercaseMap[i] = toUChar;
            ++toLChar;
            ++toUChar;
        }
        for (int i = 0; i < decipherDistance; ++i) {
            this.lowercaseMap[i] = toLChar;
            this.uppercaseMap[i] = toUChar;
            ++toLChar;
            ++toUChar;
        }
    }
    
    /**
     * Modify the given StringBuffer by applying this RotationCipher's
     * algorithm to it.  This may or may not actually decrypt the StringBuffer
     * into English text; the caller must decide if this RotationCipher's
     * algorithm actually "worked."
     *
     * @param cryptogram    the StringBuffer to be modified
     */
    public void decipher(StringBuffer cryptogram) {
        for (int i = 0; i < cryptogram.length(); ++i) {
            char cryptochar = cryptogram.charAt(i);
            
            if (Character.isLowerCase(cryptochar)) {
                cryptogram.setCharAt(i, this.lowercaseMap[cryptochar - 'a']);
            } else if (Character.isUpperCase(cryptochar)) {
                cryptogram.setCharAt(i, this.uppercaseMap[cryptochar - 'A']);
            } else {
                // Do nothing.
            }
        }
    }
}

// End of file.

