#!/usr/bin/python3.6
# -*- coding: utf-8 -*-

import sys
sys.path.insert(0, "../lib")
from utils import *
from validator import *
import argparse
import enchant

def set_args():
    global args
    parser = argparse.ArgumentParser()
    parser.add_argument("-t", "--text", help="text to read from. If not specified the program will read from standard input")
    parser.add_argument("-k", "--key", help="key used to encrypt. If no key is provided the program will try to crack and decrypt using the specified language", type=int)
    parser.add_argument("-l", "--lang", help=f"available languages: {enchant.list_languages()} (default: en_US). Only useful if no key is provided", default='en_US')
    parser.add_argument("-V", "--verbose", action='store_true', help="show extra information")
    parser.add_argument("-A", "--all", action='store_true', help="show decrypted text for each tested key")
    parser.add_argument("-D", "--debug", action='store_true', help="show information about text validation")
    parser.add_argument("-T", "--threshold", help="valid word count percentage to mark the whole text as valid language (default: 50)", type=int, default=50)
    parser.add_argument("--beep", action='store_true', help="plays a beep sound when program finishes. May require SOX to be installed")
    args = parser.parse_args()

def caesar(text, shift):
    """Encrypts/Decrypts a `text` using the caesar substitution cipher with specified `shift` key"""
    if shift < 0 or shift > MODULE:
        error(f"key must be between 0 and {MODULE}")
    return ''.join(map(lambda char: shift_by(char, shift), text))

def crack(text, terminal=True):
    """Cracks the text that must be encrypted with the caesar cipher"""
    shifts = reversed_shifts(clean(text), args.verbose)
    for i, shift in enumerate(shifts):
        decrypt = caesar(text, shift)
        if args.verbose:
            sys.stdout.write("\r")
            sys.stdout.write(f"Testing '{FREQUENCY_ALPHABET[i]}' (ROT-{shift})       ")
            sys.stdout.flush()
        if args.all:
            print(f'Testing decrypted text:\n"{decrypt}"')
        if args.verbose and args.debug:
            print()
        if validator.is_valid(decrypt):
            encryptionKey = (MODULE - shift)%MODULE
            if terminal:
                if args.verbose:
                    validator.success()
                    if args.debug:
                        print()
                    print(f'Decrypted with ROT-{shift}. Original encryption key: {encryptionKey}')
                print(decrypt)
            return (encryptionKey, decrypt)
        if args.debug:
            print()
    if args.verbose and not args.debug:
            print()
    if terminal:
        validator.fail()
    return FAILED

if __name__ == "__main__":
    set_args()

    validator = Validator(args.lang, args.threshold, args.debug, args.beep)
    text = read(args.text)

    if args.key is not None:
        if args.verbose:
            print(f"Original text most frequent character: {most_frequent_char(clean(text))}\n")
        encrypted = caesar(text, args.key)
        print(encrypted)
        if args.verbose:
            print(f"\nEncrypted text most frequent character: {most_frequent_char(clean(encrypted))}")
    else:
        crack(text)