{---  
 - AutoKey Cipher Implementation
 ---
 - The AutoKey Cipher as defined by the American Cryptographers Association:
 - 		http://www.cryptogram.org/cdb/aca.info/aca.and.you/chap08.html#AUTOKE
 -
 - AutoKey is a classic pedagogical cipher and should not be used for security
 - applications. Used AES or another current and secure cipher.
 -
 - During encryption, the key is the plaintext appended to the given key. 
 - During decryption, the key is the given key with partially decrypted
 - plaintext added as needed (essentially, same as decryption). 
 - 
 - This implementation toUppers the letters, and only works with characters from
 - 'A' to 'Z' (ASCII codes 60 to 95). It keeps all text formatting, numbers, etc
 - the same.
 -
 - Notes: This is my first experiment with Haskell. I found it infuriating and 
 -        enjoyable at the same time. Comments/suggestions are welcome (unless 
 -		  you're reading this many years from its creation)! Special thanks go 
 -		  out to the endlessly patient folks of #haskell on freenode.
 -
 - Written by: Richard Carback (carback1@umbc.edu)
 - Last Modified: July 11th, 2008 6:15 pm EST
 -
 - License:
 -
 - Permission is hereby granted, free of charge, to any person obtaining a copy
 - of this software and associated documentation files (the "Software"), to deal
 - in the Software without restriction, including without limitation the rights
 - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 - copies of the Software, and to permit persons to whom the Software is
 - furnished to do so, subject to the following conditions:
 - 
 - The above copyright notice and this permission notice shall be included in
 - all copies or substantial portions of the Software.
 - 
 - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 - THE SOFTWARE.
 -}

module Main where

import System (getArgs, getProgName)
import Char (chr, ord, toUpper)
import List (zipWith)


-- Decryption --
autokey_decrypt file key = adcipher file (filter (<=90) (filter (>=65) key))
-- This is more complicated than decryption, because you can get negative nums.
admod x y = let diff = (x-y)
			in if diff >= 0 then diff + 65
			   else 26 + diff + 65
			   
adcipher [] (k:kx) = []
adcipher (c:cx) (k:kx) = if c >= 65 && c <= 90 then
							let p = (admod c k)
						 	in [p] ++ adcipher cx (kx ++ [p])
					 	else [c] ++ adcipher cx (k:kx)
						 	
-- Encryption --
autokey_encrypt file key = aecipher file (filter (<=90) (filter (>=65) key))
aemod x y = ((x + y) `mod` 65) `mod` 26 + 65
aecipher [] (k:kx) = []
aecipher (p:px) (k:kx) = if p >= 65 && p <= 90 then
						 	let c = (aemod p k)
						 	in [c] ++ aecipher px (kx ++ [p])
					 	else [p] ++ aecipher px (k:kx)

		 
format x = map ord (map toUpper x)

usage = do 
		 x <- getProgName
		 putStrLn ("Usage: " ++ x ++ " <d|e> <file> <key>")

main = do
		x <- getArgs
		if length x == 3
			then do 
				f <- readFile (x !! 1)
				let file = format f
				let	key = (format (x !! 2))
				putStrLn (map chr file)
				putStrLn "\n -- \n"
				if x !! 0 == "d"
					then putStrLn (map chr (autokey_decrypt file key))
					else if x !! 0 == "e"
						then putStrLn (map chr (autokey_encrypt file key))
					else usage
			else usage

