import sys
import traceback
import json

from context import GenericServerError


def handle_exception(exception, logger):
    exc_info = sys.exc_info()
    stack = traceback.extract_stack()
    tb = traceback.extract_tb(exc_info[2])
    full_tb = stack[:-1] + tb
    exc_line = traceback.format_exception_only(*exc_info[:2])
    traceback_info = '\n'.join([
        'Traceback (most recent call last)',
        ''.join(traceback.format_list(full_tb)),
        ''.join(exc_line)
    ])
    logger.error('Exception caught:\n{0}'.format(traceback_info))
    return GenericServerError('unexpected exception', traceback_info)


def print_traceback(e, logger=None):
    exc_info = sys.exc_info()
    stack = traceback.extract_stack()
    tb = traceback.extract_tb(exc_info[2])
    full_tb = stack[:-1] + tb
    exc_line = traceback.format_exception_only(*exc_info[:2])
    traceback_info = '\n'.join([
        'Exception: {}'.format(repr(e)),
        'Traceback:',
        ''.join(traceback.format_list(full_tb)),
        ''.join(exc_line)
    ])
    if logger is not None:
        logger.error(traceback_info)
    else:
        print(traceback_info)


def dumpjs(value, ind=4, sort=False):
    return json.dumps(value, indent=ind, sort_keys=sort)


def add_to_json(js, path, value, logger=None):
    if logger is not None:
        logger.debug('[add_to_json] js[{}] = {}'.format(path, dumpjs(value)))
    add_to_json_rec(js, path.split('.'), value)


def add_to_json_rec(js, parts, value):
    if len(parts) == 1:
        js[parts[0]] = value
    else:
        if parts[0] not in js:
            js[parts[0]] = {}
        add_to_json_rec(js[parts[0]], parts[1:], value)


class InternalError(Exception):

    def __init__(self, msg):
        Exception.__init__(self, msg)


def get_link_pool_id(collection, link_ot, link_field=None):

    # check if the linked object has pool management
    for table_js in collection.datamodel['schema']['tables']:
        if table_js['name'] == link_ot:
            has_pool_link = table_js['pool_link'] if 'pool_link' in table_js else False
            if not has_pool_link:
                return None

    if link_field is not None and \
            isinstance(collection.linked_object_pools, dict) and link_field in collection.linked_object_pools:
        try:
            return collection.linked_object_pools[link_field]['pool']['_id']
        except KeyError:
            print("KeyError: {}".format(collection.linked_object_pools[link_field]))

    if collection.linked_pool_id is not None:
        return collection.linked_pool_id

    return collection.pool_id
