import mysql.connector
import mysql.connector.constants
import mysql.connector.errors
import time
from requests.structures import CaseInsensitiveDict as CIDict
import psycopg2

# There could be ImportError and taos.error.InterfaceError,
# anyway, we just catch Exception
try:
    import taos
except Exception as unused:
    pass

def getTime():
    return int(time.time())

def get_mysql_conn_params(host, port, user, password, dbname):
    mysql_conn_params = {}
    mysql_conn_params['host'] = host
    mysql_conn_params['port'] = port
    mysql_conn_params['user'] = user
    mysql_conn_params['password'] = password
    mysql_conn_params['database'] = dbname
    mysql_conn_params['use_pure'] = True
    if 'ssl_disabled' in mysql.connector.constants.DEFAULT_CONFIGURATION:
        mysql_conn_params['ssl_disabled'] = True
    return mysql_conn_params

def getString(val):
    if type(val) is not str:
        return val.decode()
    else:
        return val

# return None on database error
def getMySQLConn(host, port, user, password, dbname):
    mysql_conn_params = get_mysql_conn_params(host, port, user, password, dbname)
    conn = None
    try:
        conn = mysql.connector.connect(**mysql_conn_params)
    except mysql.connector.errors.Error as err:
        # TODO: print/show the error
        pass
    return conn

def getTaosConn(host, port, user, password, dbname):
    conn = None
    conn = taos.connect(host=host, port=port, user=user, password=password, database=dbname)
    return conn


def clearMySQLCursorRecs(cur):
    fetchCount = 50000
    try:
        while True:
            unused = cur.fetchmany(fetchCount)
            if unused is None or len(unused) == 0:
                break
    except mysql.connector.errors.Error as err:
        pass

def closeMySQLCursor(cur):
    if cur is None:
        return
    try:
        cur.close()
    except mysql.connector.errors.Error as err:
        pass

def closeMySQLConnection(conn):
    if conn is None:
        return
    try:
        conn.close()
    except mysql.connector.errors.Error as err:
        pass

def getMetaSeeds(jscfg):
    return jscfg['meta']['group_seeds']

def getResultUsingConn(conn, sql):
    cur = conn.cursor()
    rows = getResultUsingCursor(cur, sql)
    cur.close()
    return rows

def executeUsingConn(conn, sql):
    cur = conn.cursor()
    cur.execute(sql)
    cur.close()

def getResultMapUsingConn(conn, sql):
    cur = conn.cursor(dictionary=True)
    rows = getResultUsingCursor(cur, sql)
    cur.close()
    return rows

def getResultUsingCursor(cur, sql):
    cur.execute(sql)
    rows = cur.fetchall()
    return rows

def getTableTupleList(conn, tbname):
    sql = "select * from %s" % tbname
    return getResultUsingConn(conn, sql)

def getTableDictList(conn, tbname):
    sql = "select * from %s" % tbname
    return getResultMapUsingConn(conn, sql)

def getResultDictList(conn, sql):
    return getResultMapUsingConn(conn, sql)

def getResultTupleList(conn, sql):
    return getResultUsingConn(conn, sql)

def getHostListByType(conn, mtype):
    sql = "select * from server_nodes where machine_type='%s'" % mtype
    return getResultDictList(conn, sql)

def get_storage_hosts(conn):
    return getHostListByType(conn, 'storage')

def get_computing_hosts(conn):
    return getHostListByType(conn, 'computer')

# to get storage host list: get_hostlist(get_storage_hosts(conn))
# to get server host list: get_hostlist(get_computing_hosts(conn))
def get_hostlist(itemarr):
    hosts = []
    for item in itemarr:
        hosts.append(item['hostaddr'])
    return hosts

def get_storage_hostlist(conn):
    return get_hostlist(get_storage_hosts(conn))

def get_computing_hostlist(conn):
    return get_hostlist(get_computing_hosts(conn))

def get_clusters(conn):
    sql = "select * from db_clusters where status='inuse' "
    return getResultDictList(conn, sql)

def get_all_clusters(conn):
    sql = "select * from db_clusters"
    return getResultDictList(conn, sql)

def get_shards(conn, cluster_id):
    sql = "select * from shards where db_cluster_id=%s and status='inuse' " % str(cluster_id)
    return getResultDictList(conn, sql)

def get_shard_nodes(conn, cluster_id, shard_id):
    sql = "select * from shard_nodes where db_cluster_id=%s and shard_id=%s and status='active' " % (str(cluster_id), str(shard_id))
    return getResultDictList(conn, sql)

def get_shard_source(conn, cluster_id, shard_id):
    sql = "select * from shard_nodes where db_cluster_id=%s and shard_id=%s and member_state='source' and status='active' " % (str(cluster_id), str(shard_id))
    return getResultDictList(conn, sql)[0]

def get_shard_replicas(conn, cluster_id, shard_id):
    sql = "select * from shard_nodes where db_cluster_id=%s and shard_id=%s and member_state='replica' and status='active' " % (str(cluster_id), str(shard_id))
    return getResultDictList(conn, sql)

def get_proxysql_nodes(conn, cluster_id):
    sql = "select * from proxysql_nodes where db_cluster_id=%s and status='active' " % str(cluster_id)
    return getResultDictList(conn, sql)

# No status field
def get_meta_nodes(conn):
    sql = "select * from meta_db_nodes"
    return getResultDictList(conn, sql)

def get_meta_source(conn):
    sql = "select * from meta_db_nodes where member_state='source'"
    return getResultDictList(conn, sql)[0]

def get_meta_replicas(conn):
    sql = "select * from meta_db_nodes where member_state='replica'"
    return getResultDictList(conn, sql)

def get_meta_hamode(conn):
    sql = "select value from global_configuration where name='meta_ha_mode'"
    return getResultDictList(conn, sql)[0]['value']

def get_comp_nodes(conn, cluster_id):
    sql = "select * from comp_nodes where db_cluster_id=%s and status='active'" % str(cluster_id)
    return getResultDictList(conn, sql)

# No status field
def get_clustermgr_nodes(conn):
    sql = "select * from cluster_mgr_nodes"
    return getResultDictList(conn, sql)

def get_clustermgr_source(conn):
    sql = "select * from cluster_mgr_nodes where member_state='source'"
    return getResultDictList(conn, sql)[0]

def get_clustermgr_replicas(conn):
    sql = "select * from cluster_mgr_nodes where member_state='replica'"
    return getResultDictList(conn, sql)

def get_cdc_server(conn):
    sql = "select * from cluster_cdc_server"
    return getResultDictList(conn, sql)

def get_backup_storage(conn):
    sql = "select * from backup_storage"
    return getResultDictList(conn, sql)

def get_cdc_jobstates(conn):
    sql = "select * from cdc_job_state"
    return getResultDictList(conn, sql)

def get_cdc_jobstate(conn, jobid):
    sql = "select * from cdc_job_state where id=%s" % str(jobid)
    return getResultDictList(conn, sql)

def get_cdc_workers(conn):
    sql = "select * from cluster_cdc_worker"
    return getResultDictList(conn, sql)

def get_mongo_url(host, port, user, passwd):
    if user == "":
        return "%s:%s" % (host, str(port))
    else:
        return "%s:%s@%s:%s" % (user, passwd, host, str(port))

def fix_dbname(dbname,  separator="$$"):
    return "postgres_%s_%s" % (separator, dbname)

def create_PgDatabase(host, port, user, passwd, dbname):
    conn_params = {
    'dbname': 'postgres',
    'user': user,
    'password': passwd,
    'host': host,
    'port': port
    }
    conn = psycopg2.connect(**conn_params)
    conn.autocommit = True
    cursor = conn.cursor()
    cursor.execute("CREATE DATABASE if not exists %s;" % dbname)
    cursor.close()
    conn.close()

def create_Klustron_MysqlDatabase(host, port, user, passwd, dbname, pgdb='postgres'):
    conn = getMySQLConn(host, port, user, passwd, "%s.public" % pgdb)
    cursor = conn.cursor()
    cursor.execute('create database if not exists %s;' % dbname)
    cursor.close()
    conn.close()
    



