#!/usr/bin/env python
import argparse

from purdy.actions import Append, AppendTypewriter
from purdy.cmd import (num_arg, filename_arg, highlight_arg, ansi_args, 
    rtf_args, general_args)
from purdy.content import Code, Listing
from purdy.scribe import (print_ansi, print_tokens, print_html, print_rtf,
    range_set_to_list)
from purdy.settings import settings
from purdy.ui import SimpleScreen

# =============================================================================

DESCRIPTION = """Purdy is a library and set of command line tools for
displaying code. You can write your own code to display specific content using
the library, or use the subcommands of this program for preset usages. The
'purdy' command uses the Urwid library to display a colourized version of your
code in the console, and is a wrapper to the subcommand of the same name.
"""

# =============================================================================
# Commands
# =============================================================================

# -----------------------------------------------------------------------------
# "purdy" sub-command

def sub_purdy(args):
    ### "purdy" sub-command; uses urwid to do typewriter display of code
    settings['deactivate_args'] = True

    # calulcate our typing settings delays
    if args.delay:
        settings['delay'] = args.delay
    elif args.wpm:
        # in typing class, wpm calc is based on 5 letter words, change number of
        # words into letters per second then invert to get delay
        settings['delay'] = 1000 / (5 * args.wpm  / 60)

    if args.variance:
        settings['delay_variance'] = args.variance

    if args.x16:
        settings['colour'] = 16

    # initialize our display screen using a single code listing box
    screen = SimpleScreen(settings=settings)
    code_box = screen.code_box

    # read the code being displayed and create the appropriate action
    blob = Code(args.filename, lexer_name=args.lexer)

    if args.continuous:
        action = Append(code_box, blob)
    else:
        action = AppendTypewriter(code_box, blob)

    # --- All set, run it
    screen.run([action])

# -----------------------------------------------------------------------------
# "tokens" sub-command

def tokens(args):
    ### 'tokens' sub-command: prints lines and tokens to screen
    code = Code(lexer_name=args.lexer, filename=args.filename)
    listing = Listing(code)
    print_tokens(listing, not args.blackandwhite)

# -----------------------------------------------------------------------------
# "print" sub-command

def sub_print(listing, args):
    ### 'print' sub-command: prints colourized code to screen 
    listing.set_display('ansi')
    print_ansi(listing)

# -----------------------------------------------------------------------------
# "html" sub-command

def html(listing, args):
    ### 'html' sub-command: formats as html div and prints to screen
    listing.set_display('html')
    print_html(listing, not args.full)

# -----------------------------------------------------------------------------
# "rtf" sub-command

def rtf(listing, args):
    ### 'rtf' sub-command: formats as rtf document, prints to screen
    listing.set_display('rtf')
    bg = None
    if args.background:
        bg = args.background

    print_rtf(listing, bg)

# -----------------------------------------------------------------------------
# printable -- called for print, html and rtf sub-commands

def printable(args):
    code = Code(lexer_name=args.lexer, filename=args.filename)
    listing = Listing(code, starting_line_number=args.num)

    if args.highlight:
        for num in range_set_to_list(args.highlight):
            listing.set_highlight(True, num, num)

    args.subfunc(listing, args)

# =============================================================================
# Main
# =============================================================================

parser = argparse.ArgumentParser(description=DESCRIPTION)

# === Common flags ===
general_args(parser)

# === Subcommands ===
subparsers = parser.add_subparsers(title='subcommands', dest='command')
subparsers.required = True

# --- purdy cmd
sub = subparsers.add_parser('purdy', help=('Display code in a interactive '
    'console window. Code is written to the screen as if it is being '
    'typed'))
sub.set_defaults(func=sub_purdy)

sub.add_argument('-c', '--continuous', action='store_true', 
    help=('Instead of prentending to type like a human, just dump the file '
    'to the screen'))

sub.add_argument('-x16', action='store_true', help=('Force 16 colour '
    'terminal mode in case 256 is not working to the screen'))

# set up the typing_delay / words_per_minute options
group = sub.add_mutually_exclusive_group()
group.add_argument('-d', '--delay', type=int, 
    help=('Amount of time between each letter when in typewriter mode. '
        'Specified in milliseconds. Defaults to %sms' % settings['delay'] ))
group.add_argument('-w', '--wpm', type=int, help=('Number of words per '
    'minute that the typing speed should look like'))
sub.add_argument('--variance', type=int,
    help=('To make the typing look more real there is a variance in the '
        'delay between keystrokes. This value, in milliseconds is how '
        'much to go over or under the delay by. Defaults to +/- 30ms'))

# --- tokens cmd
sub = subparsers.add_parser('tokens', help=('Prints out each line in a '
    'file with the corresponding tokens indented beneath it'))
sub.set_defaults(func=tokens)

sub.add_argument('--blackandwhite', '--bw', help=('By default code lines '
    'are highlighted using ANSI colour. This flag turns this off.'), 
    action='store_true')

# --- print cmd
sub = subparsers.add_parser('print', help=('Prints code to screen using '
    'colourized ANSI escape sequences'))
sub.set_defaults(func=printable, subfunc=sub_print)
ansi_args(sub)

# --- html cmd
sub = subparsers.add_parser('html', help=('Prints code to screen formatted '
    'as an HTML div'))
sub.set_defaults(func=printable, subfunc=html)
num_arg(sub)
highlight_arg(sub)

sub.add_argument('--full', help=('By default only a snippet of HTML is '
    'displayed inside a <div>. This flag produces a full HTML document.'),
    action='store_true')

# --- rtf cmd
sub = subparsers.add_parser('rtf', help=('Prints code to screen formatted '
    'as an RTF document'))
sub.set_defaults(func=printable, subfunc=rtf)
rtf_args(sub)

# === Positional filename argument common to all subs
filename_arg(parser)

if __name__ == '__main__':
    ### Execute ###
    args = parser.parse_args()
    args.func(args)
