import logging
import os
import json
from typing import Dict

from requests.exceptions import HTTPError
from brian_dashboard_manager.grafana.utils.request import Request, TokenRequest


logger = logging.getLogger(__name__)


def _datasource_provisioned(datasource_to_check, provisioned_datasources):
    if len(datasource_to_check.keys()) == 0:
        return True
    for datasource in provisioned_datasources:
        exists = all(datasource.get(key) == datasource_to_check.get(key)
                     for key in datasource_to_check)
        if exists:
            return True
    return False


def get_missing_datasource_definitions(request: Request, dir=None):
    datasource_dir = dir or os.path.join(
        os.path.dirname(__file__), '../datasources/')
    existing_datasources = get_datasources(request)

    def check_ds_not_provisioned(filename):
        datasource = json.load(open(filename, 'r'))
        if not _datasource_provisioned(datasource, existing_datasources):
            return datasource

    for (dirpath, _, filenames) in os.walk(datasource_dir):  # pragma: no cover
        for file in filenames:
            if not file.endswith('.json'):
                continue
            filename = os.path.join(dirpath, file)
            yield check_ds_not_provisioned(filename)


def check_provisioned(request: TokenRequest, datasource):
    existing_datasources = get_datasources(request)
    return _datasource_provisioned(datasource, existing_datasources)


def get_datasources(request: Request):
    return request.get('api/datasources')


def create_datasource(request: TokenRequest, datasource: Dict, datasources):
    try:
        ds_type = datasource["type"]
        # find out which params
        # we need to configure for this datasource type
        config = datasources.get(ds_type, None)
        if config is None:
            logger.exception(
                f'No datasource config could be found for {ds_type}')
            return None
        datasource.update(config)
        r = request.post('api/datasources', json=datasource)
    except HTTPError:
        logger.exception('Error when provisioning datasource')
        return None
    return r


def delete_datasource(request: TokenRequest, name: str):
    return request.delete(f'api/datasources/name/{name}')