import getpass
import inspect
import sys
import client
import connection
from client import allowed_commands
from connection import client_request
from tabulate import tabulate

from util import debug


def login(username=None, password=None):
    if connection.session_id is not None:
        client.fake_loading_bar('Signing out', delay=0.025)
        connection.session_id = None

    if username is None:
        username = input('Username: ')

    if password is None:
        if sys.stdin.isatty():
            password = getpass.getpass('Password: ')
        else:
            password = input('Password: ')

    response = client_request('login', {"username": username, "password": password})
    success = 'session_id' in response
    if success:
        connection.session_id = response['session_id']
        print('Login successful.')
    else:
        if 'error_message' in response:
            print('Login failed with message:', response['error_message'])
        else:
            print('Login failed.')


def register(username=None, password=None, game_key=''):
    if connection.session_id is not None:
        client.fake_loading_bar('Signing out', delay=0.025)
        connection.session_id = None

    if username is None:
        username = input('Username: ')

    if password is None:
        if sys.stdin.isatty():
            password = getpass.getpass('Password: ')
        else:
            password = input('Password: ')

    if not debug:
        if game_key is '':
            print('Entering a game key will provide you with some starting money and other useful stuff.')
            game_key = input('Game key (leave empty if you don\'t have one): ')

    response = client_request('register', {"username": username, "password": password, "game_key": game_key})

    if 'error_message' in response:
        print('Registration failed with message:', response['error_message'])


# noinspection PyShadowingBuiltins
def help():
    print('Allowed commands:')
    for cmd in allowed_commands:
        this_module = sys.modules[__name__]
        method = getattr(this_module, cmd)
        params = inspect.signature(method).parameters
        num_args = len(params)
        if num_args > 0:
            print('`' + cmd + '`', 'takes the following', num_args, 'arguments:')
            for p in params:
                print(' -', p)  # TODO print default value
        else:
            print('`' + cmd + '`', 'takes no arguments')

    print('NOTE: All arguments are optional!')


def depot():
    response = client_request('depot', {"session_id": connection.session_id})
    success = 'data' in response
    if success:
        print(tabulate(response['data'], headers=['Object', 'Amount'], tablefmt="pipe"))
    else:
        if 'error_message' in response:
            print('Depot access failed with message:', response['error_message'])
        else:
            print('Depot access failed.')


def activate_key(key=''):
    if key == '':
        print('Entering a game key may get you some money or other useful stuff.')
        key = input('Key: ')

    if key == '':
        print('Invalid key.')

    response = client_request('activate_key', {"session_id": connection.session_id, 'key':key })
    if 'error_message' in response:
        print('Key activation failed with message:', response['error_message'])


def yn_dialog(msg):
    while True:
        result = input(msg + ' [y/n]: ')
        if result == 'y':
            return True
        if result == 'n':
            return False


def buy(amount=None, object_name=None, limit='', stop_loss=''):
    if object_name is None:  # TODO list some available objects
        object_name = input('Name of object to buy: ')
    if amount is None:
        print('Entering a game key may get you some money or other useful stuff.')
        amount = input('Amount: ')
    if limit != '':
        set_limit = yn_dialog('Do you want to place a limit?')
        if set_limit:
            limit = input('Limit: ')
            stop_loss = yn_dialog('Is this a stop-loss limit?')
    response = client_request('order', {"buy": True,
                                        "session_id": connection.session_id,
                                        "amount":amount,
                                        "ownable": object_name,
                                        "limit": limit,
                                        "stop_loss": stop_loss})
    if 'error_message' in response:
        print('Order placement failed with message:', response['error_message'])


def orders():
    response = client_request('orders', {"session_id": connection.session_id})
    success = 'data' in response
    if success:
        print(tabulate(response['data'],
                       headers=['Buy?', 'Name', 'Amount', 'Limit', 'Stop Loss?', 'Orig. Order Size'],
                       tablefmt="pipe"))
    else:
        if 'error_message' in response:
            print('Order access failed with message:', response['error_message'])
        else:
            print('Order access failed.')