import logging
import os
import platform
from mycli import __version__
from mycli.packages.special import iocommands
from mycli.packages.special.utils import format_uptime
from .main import special_command, RAW_QUERY, PARSED_QUERY
from pymysql import ProgrammingError

log = logging.getLogger(__name__)


@special_command("\\dt", "\\dt[+] [table]", "List or describe tables.", arg_type=PARSED_QUERY, case_sensitive=True)
def list_tables(cur, arg=None, arg_type=PARSED_QUERY, verbose=False):
    if arg:
        query = "SHOW FIELDS FROM {0}".format(arg)
    else:
        query = "SHOW TABLES"
    log.debug(query)
    cur.execute(query)
    tables = cur.fetchall()
    status = ""
    if cur.description:
        headers = [x[0] for x in cur.description]
    else:
        return [(None, None, None, "")]

    if verbose and arg:
        query = "SHOW CREATE TABLE {0}".format(arg)
        log.debug(query)
        cur.execute(query)
        status = cur.fetchone()[1]

    return [(None, tables, headers, status)]


@special_command("\\l", "\\l", "List databases.", arg_type=RAW_QUERY, case_sensitive=True)
def list_databases(cur, **_):
    query = "SHOW DATABASES"
    log.debug(query)
    cur.execute(query)
    if cur.description:
        headers = [x[0] for x in cur.description]
        return [(None, cur, headers, "")]
    else:
        return [(None, None, None, "")]


@special_command("status", "\\s", "Get status information from the server.", arg_type=RAW_QUERY, aliases=("\\s",), case_sensitive=True)
def status(cur, **_):
    query = "SHOW GLOBAL STATUS;"
    log.debug(query)
    try:
        cur.execute(query)
    except ProgrammingError:
        # Fallback in case query fail, as it does with Mysql 4
        query = "SHOW STATUS;"
        log.debug(query)
        cur.execute(query)
    status = dict(cur.fetchall())

    query = "SHOW GLOBAL VARIABLES;"
    log.debug(query)
    cur.execute(query)
    variables = dict(cur.fetchall())

    # prepare in case keys are bytes, as with Python 3 and Mysql 4
    if isinstance(list(variables)[0], bytes) and isinstance(list(status)[0], bytes):
        variables = {k.decode("utf-8"): v.decode("utf-8") for k, v in variables.items()}
        status = {k.decode("utf-8"): v.decode("utf-8") for k, v in status.items()}

    # Create output buffers.
    title = []
    output = []
    footer = []

    title.append("--------------")

    # Output the mycli client information.
    implementation = platform.python_implementation()
    version = platform.python_version()
    client_info = []
    client_info.append("mycli {0},".format(__version__))
    client_info.append("running on {0} {1}".format(implementation, version))
    title.append(" ".join(client_info) + "\n")

    # Build the output that will be displayed as a table.
    output.append(("Connection id:", cur.connection.thread_id()))

    query = "SELECT DATABASE(), USER();"
    log.debug(query)
    cur.execute(query)
    db, user = cur.fetchone()
    if db is None:
        db = ""

    output.append(("Current database:", db))
    output.append(("Current user:", user))

    if iocommands.is_pager_enabled():
        if "PAGER" in os.environ:
            pager = os.environ["PAGER"]
        else:
            pager = "System default"
    else:
        pager = "stdout"
    output.append(("Current pager:", pager))

    output.append(("Server version:", "{0} {1}".format(variables["version"], variables["version_comment"])))
    output.append(("Protocol version:", variables["protocol_version"]))

    if "unix" in cur.connection.host_info.lower():
        host_info = cur.connection.host_info
    else:
        host_info = "{0} via TCP/IP".format(cur.connection.host)

    output.append(("Connection:", host_info))

    query = "SELECT @@character_set_server, @@character_set_database, " "@@character_set_client, @@character_set_connection LIMIT 1;"
    log.debug(query)
    cur.execute(query)
    charset = cur.fetchone()
    output.append(("Server characterset:", charset[0]))
    output.append(("Db characterset:", charset[1]))
    output.append(("Client characterset:", charset[2]))
    output.append(("Conn. characterset:", charset[3]))

    if "TCP/IP" in host_info:
        output.append(("TCP port:", cur.connection.port))
    else:
        output.append(("UNIX socket:", variables["socket"]))

    if "Uptime" in status:
        output.append(("Uptime:", format_uptime(status["Uptime"])))

    if "Threads_connected" in status:
        # Print the current server statistics.
        stats = []
        stats.append("Connections: {0}".format(status["Threads_connected"]))
        if "Queries" in status:
            stats.append("Queries: {0}".format(status["Queries"]))
        stats.append("Slow queries: {0}".format(status["Slow_queries"]))
        stats.append("Opens: {0}".format(status["Opened_tables"]))
        if "Flush_commands" in status:
            stats.append("Flush tables: {0}".format(status["Flush_commands"]))
        stats.append("Open tables: {0}".format(status["Open_tables"]))
        if "Queries" in status:
            queries_per_second = int(status["Queries"]) / int(status["Uptime"])
            stats.append("Queries per second avg: {:.3f}".format(queries_per_second))
        stats = "  ".join(stats)
        footer.append("\n" + stats)

    footer.append("--------------")
    return [("\n".join(title), output, "", "\n".join(footer))]
