#!/usr/bin/env python
##
# Copyright (C) 2013 Jessica T. (Tsyesika) <xray7224@googlemail.com>
#  
# This program is free software: you can redistribute it and/or modify 
# it under the terms of the GNU General Public License as published by 
# the Free Software Foundation, either version 3 of the License, or 
# (at your option) any later version. 
# 
# This program is distributed in the hope that it will be useful, 
# but WITHOUT ANY WARRANTY; without even the implied warranty of 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
# GNU General Public License for more details. 
#
# You should have received a copy of the GNU General Public License 
# along with this program. If not, see <http://www.gnu.org/licenses/>.
##

import json
import sys
import os
from pypump import PyPump

try:
    from IPython.frontend.terminal.embed import InteractiveShellEmbed
    from IPython.config.loader import Config
except ImportError:
    print("You need to have ipython installed to run this")
    sys.exit(1)

store_path = os.path.expanduser("~/.pypump_test")


welcome_banner = """Welcome to the PyPump testing shell,
We have setup some useful objects for you:

{table}

If you need help please visit our docs:
https://pypump.readthedocs.org/en/latest

Enjoy!
"""

def ascii_table(headings, data):
    """ Draws an ascii table """
    # first we need to work out how long each column should be
    columns = {}
    for heading in headings:
        columns[heading] = len(heading)+1 # plus one for the extra padding

    # data could also overspill
    for record in data:
        for heading, d in record.items():
            dlen = len(d)+1
            if dlen > columns[heading]:
                columns[heading] = dlen


    table = {}
    # okay now we need to pad the headers readying for drawing
    for column, width in columns.items():
        table[column] = "{name}{padding}".format(
                name=column, padding=" "*(width-len(column))
                )

    heading = "| "
    for column in table.values():
        heading += column
        heading += "| "

    # now for the data
    table = {}
    for i, record in enumerate(data):
        table[i] = "| "
        for column, cdata in record.items():
            table[i] += "{data}{padding} | ".format(
                    data=cdata, padding=" "*(columns[column]-len(cdata)-1)
                    )

    # make the helper function which will draw the seporators
    def draw_sep(columns):
        """ Draws +----+--- etc... """
        sep = "+"
        for width in columns:
            sep += "-"*(width+1)
            sep += "+"

        return sep + "\r\n"

    sepper = lambda :draw_sep(columns.values())
    stable = sepper()
    stable += heading + "\r\n"
    stable += sepper()
    for value in table.values():
        stable += value + "\r\n"
    
    stable += sepper()
    return stable # few, glad that's over

    

def open_database(path):
    if os.path.exists(path):
        try:
            fin = open(path, "r")
            db = json.loads(fin.read())
            return db
        except Exception:
            print("There has been a problem parsing the database {0}".format(path))
            sys.exit(1)

    else:
        return {}

def save_database(db, path):
    """ Saves db as JSON to path """
    if os.path.exists(path):
        try:
            os.remove(path)
        except Exception:
            print("There was an error removing database from {0}".format(path))
    try:
        fout = open(path, "w")
        db = json.dumps(db, sort_keys=True, indent=4, separators=(",", ": "))
        fout.write(db)
        fout.close()
    except Exception:
        raise
        print("There was an error saving the database to {0}".format(path))

    return db

if __name__ == "__main__":
    if "-h" in sys.argv or "--help" in sys.argv:
        print("Usage:")
        print("     {0} <webfinger> [client_name]".format(sys.argv[0]))
        sys.exit(0)

    if "-v" in sys.argv or "--version" in sys.argv:
        if os.path.exists("VERSION"):
            print(open("VERSION", "r").read())
        else:
            print("Unknown.")
        sys.exit(0)

    if "--clean" in sys.argv:
        if not os.path.exists(store_path):
            print("Nothing to do.")
            sys.exit(0)

        try:
            os.remove(store_path)
            print("Removed all files used by PyPump tester")
        except Exception:
            print("Something went wrong, probably permissions")
            print("The file I should have been writing to is {0}".format(store_path))
        sys.exit(0)

    # go find the client info if it exists
    db = open_database(store_path)

    webfinger = "" if len(sys.argv) <= 1 else sys.argv[1]

    if db == dict() and webfinger is None:
        print("You must specify a webfinger")
        sys.exit(1)

    for wf in db.keys():
        if webfinger in wf:
            webfinger = wf

    # okay so.
    if webfinger.find("@") == -1:
        print("Can't find webfinger {0}".format(webfinger))

    if webfinger not in db:
        if len(sys.argv) <= 2:
            client_name = "PyPump"
        else:
            client_name = sys.argv[2]
        
        db[webfinger] = {
                "client_name": client_name
                }

    else:
        client_name = db[webfinger].get("client_name", "PyPump")
        db[webfinger]["client_name"] = client_name

    
    sys.stdout.write("-> Setting up PyPump  ")
    sys.stdout.flush() # actually get it on the screen - most terms wait for \n
    pump = PyPump(
            webfinger,
            client_name=client_name,
            key=db[webfinger].get("key", None),
            secret=db[webfinger].get("secret", None),
            client_type=db[webfinger].get("client_type", "native"),
            token=db[webfinger].get("token", None),
            token_secret=db[webfinger].get("token_secret", None),
            )
    

    client = pump.get_registration()
    db[webfinger]["key"] = client[0]
    db[webfinger]["secret"] = client[1]
    db[webfinger]["expirey"] = client[2]

    tokens = pump.get_token()
    db[webfinger]["token"] = tokens[0]
    db[webfinger]["token_secret"] = tokens[1]
    
    save_database(db, store_path)

    # setup other variables for user. 
    me = pump.Person(webfinger)

    # bring curser back so banner walks over the setup message
    sys.stdout.write("\r")

    # drop them into a shell
    cfg = Config()
    cfg.InteractiveShell.confirm_exit = False
    
    # prep the welcome banner
    welcome_banner = welcome_banner.format(
            table=ascii_table(
                    ["Variable", "Representation", "Type"],
                    [
                        {
                            "Variable": "pump",
                            "Representation": str(repr(pump)),
                            "Type": type(pump).__name__,
                        },
                        {
                            "Variable": "me",
                            "Representation": str(repr(me)),
                            "Type": type(me).__name__,
                        }
                    ]
            )
    )
                    

    shell = InteractiveShellEmbed(
            config=cfg,
            banner1=welcome_banner,
            exit_msg="Remeber! Report any bugs to https://github.com/xray7224/PyPump/issues"
            )

    shell() 
