module Main (main, encode) where

import System

import Data.Bits (xor)
import Data.Char (ord, chr, toUpper)
import Text.Printf (printf)

import Text.ParserCombinators.Parsec

type IP = (Int, Int, Int, Int)

main = do
	(host:nick:_) <- getArgs
	case parse ip "command line arguments" host of
		Left err -> error $ show err
		Right host' -> putStrLn $ loginString host' nick

ip :: Parser IP
ip = do
  (a:b:c:d:[]) <- sepBy byte (char '.')
  return (a, b, c, d)

byte :: Parser Int
byte = do
  v <- int
  if (v >= 0 && v <= 255) then return v
    else fail $ "value " ++ (show v) ++ " not in byte range (0-255)"
  where int = many1 digit >>= return . read


loginString :: IP -> String -> String
loginString ip = encode ip . tetrifast

tetrifast :: String -> String
tetrifast nick = "tetrifaster " ++ nick ++ " 1.13"

encode :: IP -> String -> String
encode ip b = foldl1 (++) $ map showHex encoded
    where
      encoded    = ('\x00':) $ zipWith3 step b encoded (hashIP ip)
      step x y z = chr $ (mod (ord x + ord y) 255) `xor` (ord z)
      showHex    = (map toUpper) . (printf "%02x")

hashIP :: IP -> String
hashIP (a, b, c, d) =  cycle . show $ a * 54 + b * 41 + c * 29 + d * 17


