#!python

import click
import sys
import os
from shutil import copytree, copy
import machaao
import asyncio
from requests import request
from json import dumps
import subprocess
import shlex
import signal

FILE_DIR = os.path.dirname(os.path.abspath(machaao.__file__))

CURR_DIR = os.path.abspath(os.getcwd())

_tunnel_p = None
_chatbot_p = None

def copyany(src, dst):
    try:
        copy(src, dst)
    except OSError as exc:
        click.secho(exc, fg="red", bold=True)


@click.group()
def cli():
    """
    An easy to use module for python developers 
    looking to build and develop chatbots using 
    MACHAAO Platform. Provide the Project Name to start with the template.

    Here is an example:

    1. machaao start -n sample-chatbot

    2. machaao tunnel -p [PORT] # If chatbot token is saved on path.

    3. machaao tunnel -p [PORT] -t [TOKEN]

    You need a valid FREE API key from https://messengerx.io for the server to work. You can
    sign up for a free account at https://portal.messengerx.io.
    """
    pass


@click.command()
@click.option('-n', type=str, default='.', help="Enter the name of project.")
def start(n):

    path = os.path.join(CURR_DIR, n)

    try:
        os.mkdir(path)
    except OSError:
        raise SystemExit(0)
    
    click.secho(f'Project {n} created...', fg="blue", bold=True)
    copyany(FILE_DIR+"/chatbot.py", path+"/")
    click.secho(f'Copying files to project directory...', fg="green", bold=True)
    click.secho(f'Project Created, Keep Developing ChatBots', fg="blue", blink=True)


@click.command()
@click.option('-p', type=str, default='5000', help="Run tunnel to expose localhost to web.")
@click.option('-t', type=str, default=None, help="Run tunnel to expose localhost to web.")
@click.option('-h', type=int, default=None, help="get host name")
def tunnel(p, t, h):
    machaao_token = None

    if t != None:
        machaao_token = t

    if t == None:
        machaao_token = os.getenv("MessengerXAPIToken", None)
        if machaao_token is None:
            sys.exit(" * Chatbot token not set")


    #Not the right way of doing it only doing it for testing.
    _ws_uri = f'wss://mx.tunnel.messengerx.io/_ws/?username={machaao_token}&port={p}'

    host = None

    loop = asyncio.get_event_loop()
    try:
        if h:
            host = loop.run_until_complete(machaao.generate_host_url(ws_uri=_ws_uri))
            click.echo(str(host))
        else:
            # print(f'Incoming tunnel params: {p}....... {t}')
            loop.run_until_complete(
                machaao.open_tunnel(
                    ws_uri=_ws_uri,
                    http_uri=f'http://127.0.0.1:{p}',
                )
            )

    except KeyboardInterrupt:
        click.echo("\nMachaao tunnel closed")
    
    except Exception as e:
        if int(str(e)[6:11])== 1006:
            click.echo("\nDisconnected from MX")
            signal.signal(signal.SIGINT, exit_gracefully)
        else:
            print(e)
            print("Contact: support@messengerx.io")

#
# def sigterm_handler(signal, frame):
#     # save the state here or do whatever you want
#     print('booyah! bye bye')
#     sys.exit(0)


@click.command()
def version():
    click.echo("v0.1.9")


@click.command()
@click.option('-p', type=str, default='5000', help="Run tunnel to expose localhost to web.")
@click.option('-t', type=str, default=None, help="Run tunnel to expose localhost to web.")
def run(p, t):

    # print(f'Incoming server run params: {p}, {t}')

    _isPy = False
    _isGo = False

    if os.path.exists("chatbot.py"):
        _isPy = True

    elif os.path.exists("chatbot"):
        os.environ["PORT"] = p
        _isGo = True

    else:
        sys.exit(' * Chatbot file not present in directory')

    click.echo(f" * Validating & initializing chatbot, please wait... (can take a minute or so)")

    _p = subprocess.check_output(["machaao", "tunnel", "-p", p, "-t", t, "-h", "1"], stderr=subprocess.STDOUT)

    validated = False
    if _p:
        try:
            _p = _p.decode("utf-8").strip()
            if "messengerx.io" in _p:
                validated = True
                click.echo(f" * Validated: {_p}")
        except Exception as e:
            print(str(e))
            validated = False

    if validated:

        try:
            click.echo(f" * Initializing a chatbot for {_p}")

            # _tunnel_port = eval(p) + 1

            click.echo(f" * Initializing tunnels for chatbot for {_p}:{p}")

            _children = []
            _tunnel_p = subprocess.Popen(shlex.split(f"machaao tunnel -p {p} -t {t}"), stderr=subprocess.STDOUT)

            _chatbot_p = None

            if _isPy:
                print("runing chatbot cmd")
                _chatbot_p = subprocess.Popen(shlex.split(f'python3 chatbot.py -p {p}'), stderr=subprocess.STDOUT)
            
            if _isGo:
                _chatbot_p = subprocess.Popen(shlex.split('./chatbot'), stderr=subprocess.STDOUT)

            click.echo(f" * Chatbot for {_p} is starting...")

            chatbot_url = f"https://{_p}/machaao/incoming"

            headers = {
                "api_token": t,
                "Content-Type": "application/json",
            }

            payload = {
                "url": chatbot_url
            }

            click.echo(f" * Updating the new hook for call to - {chatbot_url}")

            request("POST", f'https://ganglia-dev.machaao.com/v1/bots/{t}', data=dumps(payload), headers=headers)

            _bot_name = _p.replace(".tunnel.messengerx.io", "")

            click.echo(click.style(f" * Your bot is now accessible @ https://dev.messengerx.io/{_bot_name}", bg="black", fg="white"))

            _chatbot_p.wait()

        except Exception as e:
            print(str(e))


    else:
        click.echo(" * oops, invalid request -- you being naughty my friend...")


cli.add_command(start)
cli.add_command(tunnel)
cli.add_command(run)
cli.add_command(version)


def exit_gracefully(signal, frame):
    if _tunnel_p:
        click.echo("terminating tunnel....")
        _tunnel_p.send_signal(signal.SIGINT)

    if _chatbot_p:
        click.echo("terminating chatbot....")
        _chatbot_p.send_signal(signal.SIGINT)

    sys.exit(0)


if __name__ == '__main__':
    signal.signal(signal.SIGINT, exit_gracefully)
    cli()
