from __future__ import absolute_import
# Let's not allow PyLint complain about string substitution
# pylint: disable=W1321,E1321

# Import python libs
import logging

# Import Salt libs
import salt.returners

# Import third party libs
try:
    import psycopg2
    import psycopg2.extras
    HAS_POSTGRES = True
except ImportError:
    HAS_POSTGRES = False

LOG = logging.getLogger(__name__)


def __virtual__():
    if not HAS_POSTGRES:
        return False, 'Could not import saltresource module; psycopg2 is not installed.'
    return 'saltresource'


def _get_options(ret=None):
    '''
    Get the postgres options from salt.
    '''
    attrs = {'host': 'host',
             'user': 'user',
             'passwd': 'passwd',
             'db': 'db',
             'port': 'port'}

    _options = salt.returners.get_returner_options('returner.postgres_graph_db',
                                                   ret,
                                                   attrs,
                                                   __salt__=__salt__,
                                                   __opts__=__opts__)
    return _options


def _get_conn(ret=None):
    '''
    Return a postgres connection.
    '''
    _options = _get_options(ret)

    host = _options.get('host')
    user = _options.get('user')
    passwd = _options.get('passwd')
    datab = _options.get('db')
    port = _options.get('port')

    return psycopg2.connect(
            host=host,
            user=user,
            password=passwd,
            database=datab,
            port=port)


def _close_conn(conn):
    '''
    Close the Postgres connection
    '''
    conn.commit()
    conn.close()


def graph_data(*args, **kwargs):
    '''
    Returns graph data for visualization app

    CLI Examples:

    .. code-block:: bash

        salt '*' saltresource.graph_data
 
    '''
    conn = _get_conn()
    cur_dict = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)

    cur_dict.execute('SELECT host, service, status FROM salt_resources')
    resources_db = [dict(res) for res in cur_dict]
    db_dict = {}

    for resource in resources_db:
        host = resource.get('host')
        service = '.'.join(resource.get('service').split('.')[:2])
        status = resource.get('status')

        if db_dict.get(host, None):
            if db_dict[host].get(service, None):
                service_data = db_dict[host][service]
                service_data.append(status)
            else:
                db_dict[host][service] = [status]
        else:
            db_dict[host] = {service: []}

    graph = []
    for host, services in db_dict.items():
        for service, statuses in services.items():
            status = 'unknown'
            if 'failed' in statuses:
                status = 'failed'
            elif 'success' in statuses and not ('failed' in statuses or 'unknown' in statuses):
                status = 'success'
            datum = {'host': host, 'service': service, 'status': status}
            graph.append(datum)

    _close_conn(conn)

    return {'graph': graph}


def host_data(host, **kwargs):
    '''
    Returns data describing single host

    CLI Examples:

    .. code-block:: bash

        salt-call saltresource.host_data '<minion_id>'
 
    '''
    conn = _get_conn()
    cur_dict = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)

    sql = 'SELECT host, service, resource_id, last_ret, status FROM salt_resources WHERE host=%s'
    cur_dict.execute(sql, (host,))
    resources_db = [dict(res) for res in cur_dict]
    db_dict = {}

    for resource in resources_db:
        host = resource.get('host')
        service = '.'.join(resource.get('service').split('.')[:2])
        status = resource.get('status')

        if db_dict.get(host, None):
            if db_dict[host].get(service, None):
                service_data = db_dict[host][service]
                service_data.append(status)
            else:
                db_dict[host][service] = [status]
        else:
            db_dict[host] = {service: []}

    graph = []

    for host, services in db_dict.items():
        for service, statuses in services.items():
            status = 'unknown'
            if 'failed' in statuses:
                status = 'failed'
            elif 'success' in statuses and not ('failed' in statuses or 'unknown' in statuses):
                status = 'success'
            resources = [{'service': r.get('service', ''), 'resource_id': r.get('resource_id', ''), 'last_ret': r.get('last_ret', None), 'status': r.get('status', '')}
                         for r
                         in resources_db
                         if r.get('service', '').startswith(service)]
            datum = {'host': host, 'service': service, 'status': status, 'resources': resources}
            graph.append(datum)

    _close_conn(conn)

    return {'graph': graph}


def sync_db(*args, **kwargs):
    conn = _get_conn()
    cur = conn.cursor()

    resources_sql = '''
      CREATE TABLE IF NOT EXISTS salt_resources (
        id            varchar(255) NOT NULL UNIQUE,
        resource_id   varchar(255) NOT NULL,
        host          varchar(255) NOT NULL,
        service       varchar(255) NOT NULL,
        module        varchar(50) NOT NULL,
        fun           varchar(50) NOT NULL,
        status        varchar(50) NOT NULL,
        options       json NULL,
        last_ret      text NULL,
        alter_time    TIMESTAMP WITH TIME ZONE DEFAULT now()
      );
    '''
    cur.execute(resources_sql)
    conn.commit()

    resources_meta_sql = '''
      CREATE TABLE IF NOT EXISTS salt_resources_meta (
        id           varchar(255) NOT NULL UNIQUE,
        options      json NULL,
        alter_time   TIMESTAMP WITH TIME ZONE DEFAULT now()
      );
    '''
    cur.execute(resources_meta_sql)
    _close_conn(conn)

    return True


def flush_db(*args, **kwargs):
    conn = _get_conn()
    cur = conn.cursor()
    result = True

    resources_sql = 'DELETE FROM salt_resources'
    try:
        cur.execute(resources_sql)
        conn.commit()
    except Exception as e:
        LOG.warning(repr(e))
        result = False

    resources_meta_sql = 'DELETE FROM salt_resources_meta'
    try:
        cur.execute(resources_meta_sql)
        _close_conn(conn)
    except Exception as e:
        LOG.warning(repr(e))
        result = False

    return result


def destroy_db(*args, **kwargs):
    conn = _get_conn()
    cur = conn.cursor()

    resources_sql = 'DROP TABLE IF EXISTS salt_resources;'
    cur.execute(resources_sql)
    conn.commit()

    resources_meta_sql = 'DROP TABLE IF EXISTS salt_resources_meta;'
    cur.execute(resources_meta_sql)
    _close_conn(conn)

    return True

