text: //
  //  CaesarCipher.cpp
  //  
  //
  //  Created by Mei-Li Holmberg on 11/7/19.
  //
  
  #include "CaesarCipher.hpp"
  
  //Default Constructor
  CaesarCipher::CaesarCipher() : CaesarCipher(0)  {
      // Create the alphabet container
      //const std::vector<char> alphabet = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};
  }
  
  CaesarCipher::CaesarCipher(int cipher_key) : key(cipher_key), alphabet({'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'}) {
      
  }
  
  CaesarCipher::CaesarCipher(std::string cipher_key) : CaesarCipher(0) {
      if ( ! cipher_key.empty() ) {
        // Before doing the conversion we should check that the string contains a
        // valid positive integer.
        // Here we do that by looping through each character and checking that it
        // is a digit. What is rather hard to check is whether the number is too
        // large to be represented by an unsigned long, so we've omitted that for
        // the time being.
        // (Since the conversion function std::stoul will throw an exception if the
        // string does not represent a valid unsigned long, we could check for and
        // handled that instead but we only cover exceptions very briefly on the
        // final day of this course - they are a very complex area of C++ that
        // could take an entire course on their own!)
        for ( const auto& elem : cipher_key ) {
          if ( ! std::isdigit(elem) ) {
        std::cerr << "[error] cipher key must be an unsigned long integer for Caesar cipher,\n"
                  << "        the supplied key (" << cipher_key << ") could not be successfully converted" << std::endl;
          }
        }
        key = std::stoul(cipher_key);
      }
  }
  
  std::string CaesarCipher::applyCipher(const std::string inputText, const CipherMode encrypt) {
      // Create the output string
      std::string outputText {};
  
  
      const size_t alphabetSize = alphabet.size();
  
      // Make sure that the key is in the range 0 - 25
      const size_t truncatedKey { key % alphabetSize };
  
      // Loop over the input text
      char processedChar {'x'};
      for ( const auto& origChar : inputText ) {
  
        // For each character in the input text, find the corresponding position in
        // the alphabet by using an indexed loop over the alphabet container
        for ( size_t i{0}; i < alphabetSize; ++i ) {
  
          if ( origChar == alphabet[i] ) {
  
        // Apply the appropriate shift (depending on whether we're encrypting
        // or decrypting) and determine the new character
        // Can then break out of the loop over the alphabet
        if ( encrypt == CipherMode::Encrypt) {
          processedChar = alphabet[ (i + truncatedKey) % alphabetSize ];
        } else {
          processedChar = alphabet[ (i + alphabetSize - truncatedKey) % alphabetSize ];
        }
        break;
          }
        }
  
        // Add the new character to the output text
        outputText += processedChar;
      }
  
      return outputText;
  }
  