import zmq
import curses

import argparse
import configparser
import threading
import time

from curses import wrapper

from client import Client
from ui import UI

def parse_args():
    parser = argparse.ArgumentParser(description='Client for teezeepee')

    # Please specify your username
    parser.add_argument('username',
                        type=str,
                        help='Specified username')

    parser.add_argument('--config-file',
                        type=str,
                        help='Default path for configuration file.')

    return parser.parse_args()


def display_section(window, display):
    window_lines, window_cols = window.getmaxyx()
    bottom_line = window_lines - 1
    window.bkgd(curses.A_NORMAL)
    window.scrollok(1)

    while True:
        window.addstr(bottom_line, 1, display.recv_string())
        window.move(bottom_line, 1)
        window.scroll(1)
        window.refresh()

def input_section(window, chat_sender):
    window.bkgd(curses.A_NORMAL)
    window.clear()
    window.box()
    window.refresh()

    while True:
        window.clear()
        window.box()
        window.refresh()
        s = window.getstr(1, 1).decode('utf-8')
        if s is not None and s != "":
            chat_sender.send_string(s)
        
        # Short pause
        time.sleep(0.01)


def main(stdscr):
    config_file = args.config_file if args.config_file is not None else 'tzp.cfg'
    config = configparser.ConfigParser()
    config.read(config_file)
    config = config['default']

    receiver = zmq.Context().instance().socket(zmq.PAIR)
    receiver.bind("inproc://clientchat")

    sender = zmq.Context().instance().socket(zmq.PAIR)
    sender.connect("inproc://clientchat")

    client = Client(args.username, config['server_host'],
                        config['chat_port'], receiver)
    client.run()

    show_receiver = zmq.Context().instance().socket(zmq.PAIR)
    show_receiver.bind("inproc://clientdisplay")

    show_sender = zmq.Context().instance().socket(zmq.PAIR)
    show_sender.connect("inproc://clientdisplay")

    ui = UI(config['server_host'], config['display_port'], show_sender)
    ui.run()

    curses.init_pair(1, curses.COLOR_BLACK, curses.COLOR_WHITE)
    curses.init_pair(2, curses.COLOR_BLACK, curses.COLOR_WHITE)

    curses.echo()
    curses.curs_set(0)

    window_height = curses.LINES
    window_width = curses.COLS
    divider =  int(window_height * 0.5)

    history_screen = stdscr.subpad(divider, window_width, 0, 0)
    input_screen = stdscr.subpad(window_height - divider, window_width, divider, 0)
    
    history_thread = threading.Thread(target=display_section, args=(history_screen, show_receiver))
    history_thread.daemon = True
    history_thread.start()

    input_thread = threading.Thread(target=input_section, args=(input_screen, sender))
    input_thread.daemon = True
    input_thread.start()

    history_thread.join()
    input_thread.join()


if '__main__' == __name__:
    try:
        args = parse_args()
        wrapper(main)

    except KeyboardInterrupt as e:
        pass
    except:
        raise


[((15, 13, 15, 72), 'argparse.ArgumentParser', 'argparse.ArgumentParser', (), '', False, 'import argparse\n'), ((61, 13, 61, 40), 'configparser.ConfigParser', 'configparser.ConfigParser', ({}, {}), '()', False, 'import configparser\n'), ((71, 13, 72, 54), 'client.Client', 'Client', ({(71, 20, 71, 33): 'args.username', (71, 35, 71, 56): "config['server_host']", (72, 24, 72, 43): "config['chat_port']", (72, 45, 72, 53): 'receiver'}, {}), "(args.username, config['server_host'], config['chat_port'], receiver)", False, 'from client import Client\n'), ((81, 9, 81, 71), 'ui.UI', 'UI', ({(81, 12, 81, 33): "config['server_host']", (81, 35, 81, 57): "config['display_port']", (81, 59, 81, 70): 'show_sender'}, {}), "(config['server_host'], config['display_port'], show_sender)", False, 'from ui import UI\n'), ((84, 4, 84, 63), 'curses.init_pair', 'curses.init_pair', ({(84, 21, 84, 22): '(1)', (84, 24, 84, 42): 'curses.COLOR_BLACK', (84, 44, 84, 62): 'curses.COLOR_WHITE'}, {}), '(1, curses.COLOR_BLACK, curses.COLOR_WHITE)', False, 'import curses\n'), ((85, 4, 85, 63), 'curses.init_pair', 'curses.init_pair', ({(85, 21, 85, 22): '(2)', (85, 24, 85, 42): 'curses.COLOR_BLACK', (85, 44, 85, 62): 'curses.COLOR_WHITE'}, {}), '(2, curses.COLOR_BLACK, curses.COLOR_WHITE)', False, 'import curses\n'), ((87, 4, 87, 17), 'curses.echo', 'curses.echo', ({}, {}), '()', False, 'import curses\n'), ((88, 4, 88, 22), 'curses.curs_set', 'curses.curs_set', ({(88, 20, 88, 21): '(0)'}, {}), '(0)', False, 'import curses\n'), ((97, 21, 97, 99), 'threading.Thread', 'threading.Thread', (), '', False, 'import threading\n'), ((101, 19, 101, 86), 'threading.Thread', 'threading.Thread', (), '', False, 'import threading\n'), ((56, 8, 56, 24), 'time.sleep', 'time.sleep', ({(56, 19, 56, 23): '(0.01)'}, {}), '(0.01)', False, 'import time\n'), ((112, 8, 112, 21), 'curses.wrapper', 'wrapper', ({(112, 16, 112, 20): 'main'}, {}), '(main)', False, 'from curses import wrapper\n'), ((65, 15, 65, 28), 'zmq.Context', 'zmq.Context', ({}, {}), '()', False, 'import zmq\n'), ((68, 13, 68, 26), 'zmq.Context', 'zmq.Context', ({}, {}), '()', False, 'import zmq\n'), ((75, 20, 75, 33), 'zmq.Context', 'zmq.Context', ({}, {}), '()', False, 'import zmq\n'), ((78, 18, 78, 31), 'zmq.Context', 'zmq.Context', ({}, {}), '()', False, 'import zmq\n')]