#
# -*- coding: utf-8 -*-
#
# This file is part of reclass (http://github.com/madduck/reclass)
#
# Copyright © 2007–14 martin f. krafft <madduck@madduck.net>
# Released under the terms of the Artistic Licence 2.0
#
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals

import posix, sys
import traceback

from reclass.defaults import REFERENCE_SENTINELS, EXPORT_SENTINELS
from reclass.utils.dictpath import DictPath

class ReclassException(Exception):

    def __init__(self, rc=posix.EX_SOFTWARE, msg=None, tbFlag=True):
        super(ReclassException, self).__init__()
        self._rc = rc
        self._msg = msg
        if tbFlag:
            self._traceback = traceback.format_exc()
        else:
            self._traceback = None
        self._full_traceback = False

    message = property(lambda self: self._get_message())
    rc = property(lambda self: self._rc)

    def __str__(self):
        return self.message + '\n' + super(ReclassException, self).__str__()

    def _get_message(self):
        if self._msg:
            return self._msg
        else:
            return 'No error message provided.'

    def exit_with_message(self, out=sys.stderr):
        if self._full_traceback:
            t, v, tb = sys.exc_info()
            print('Full Traceback', file=out)
            for l in traceback.format_tb(tb):
                print(l, file=out)
        if self._traceback:
            print(self._traceback, file=out)
        print(self.message, file=out)
        sys.exit(self.rc)


class PermissionError(ReclassException):

    def __init__(self, msg, rc=posix.EX_NOPERM):
        super(PermissionError, self).__init__(rc=rc, msg=msg)


class InvocationError(ReclassException):

    def __init__(self, msg, rc=posix.EX_USAGE):
        super(InvocationError, self).__init__(rc=rc, msg=msg)


class ConfigError(ReclassException):

    def __init__(self, msg, rc=posix.EX_CONFIG):
        super(ConfigError, self).__init__(rc=rc, msg=msg)


class DuplicateUriError(ConfigError):

    def __init__(self, nodes_uri, classes_uri):
        super(DuplicateUriError, self).__init__(msg=None)
        self._nodes_uri = nodes_uri
        self._classes_uri = classes_uri

    def _get_message(self):
        return "The inventory URIs must not be the same " \
               "for nodes and classes: {0}".format(self._nodes_uri)


class UriOverlapError(ConfigError):

    def __init__(self, nodes_uri, classes_uri):
        super(UriOverlapError, self).__init__(msg=None)
        self._nodes_uri = nodes_uri
        self._classes_uri = classes_uri

    def _get_message(self):
        msg = "The URIs for the nodes and classes inventories must not " \
              "overlap, but {0} and {1} do."
        return msg.format(self._nodes_uri, self._classes_uri)


class NotFoundError(ReclassException):

    def __init__(self, msg, rc=posix.EX_IOERR):
        super(NotFoundError, self).__init__(rc=rc, msg=msg)


class NodeNotFound(NotFoundError):

    def __init__(self, storage, nodename, uri):
        super(NodeNotFound, self).__init__(msg=None)
        self.storage = storage
        self.name = nodename
        self.uri = uri

    def _get_message(self):
        msg = "Node '{0}' not found under {1}://{2}"
        return msg.format(self.name, self.storage, self.uri)


class InterpolationError(ReclassException):

    def __init__(self, msg, rc=posix.EX_DATAERR, nodename='', uri=None, context=None, tbFlag=True):
        super(InterpolationError, self).__init__(rc=rc, msg=msg, tbFlag=tbFlag)
        self.nodename = nodename
        self.uri = uri
        self.context = context

    def _get_message(self):
        msg = '-> {0}\n'.format(self.nodename)
        msg += self._render_error_message(self._get_error_message(), 1)
        msg = msg[:-1]
        return msg

    def _render_error_message(self, message_list, indent):
        msg = ''
        for l in message_list:
            if isinstance(l, list):
                msg += self._render_error_message(l, indent + 1)
            else:
                msg += (' ' * indent * 3) + l + '\n'
        return msg

    def _add_context_and_uri(self):
        msg = ''
        if self.context:
            msg += ', at %s' % str(self.context)
        if self.uri:
            msg += ', in %s' % self.uri
        return msg


class ClassNotFound(InterpolationError):

    def __init__(self, storage, classname, path, nodename='', uri=None):
        super(ClassNotFound, self).__init__(msg=None, uri=uri, nodename=nodename)
        self.storage = storage
        self.name = classname
        self.path = path

    def _get_error_message(self):
        msg = [ 'In {0}'.format(self.uri),
                'Class {0} not found under {1}://{2}'.format(self.name, self.storage, self.path) ]
        return msg


class ClassNameResolveError(InterpolationError):
    def __init__(self, classname, nodename, uri):
        super(ClassNameResolveError, self).__init__(msg=None, uri=uri, nodename=nodename)
        self.name = classname

    def _get_error_message(self):
        msg = [ 'In {0}'.format(self.uri),
                'Class name {0} not resolvable'.format(self.name) ]
        return msg


class InvQueryClassNotFound(InterpolationError):

    def __init__(self, classNotFoundError, nodename=''):
        super(InvQueryClassNotFound, self).__init__(msg=None, nodename=nodename)
        self.classNotFoundError = classNotFoundError
        self._traceback = self.classNotFoundError._traceback

    def _get_error_message(self):
        msg = [ 'Inventory Queries:',
                '-> {0}'.format(self.classNotFoundError.nodename) ]
        msg.append(self.classNotFoundError._get_error_message())
        return msg


class InvQueryClassNameResolveError(InterpolationError):
    def __init__(self, classNameResolveError, nodename=''):
        super(InvQueryClassNameResolveError, self).__init__(msg=None, nodename=nodename)
        self.classNameResolveError = classNameResolveError
        self._traceback = self.classNameResolveError._traceback

    def _get_error_message(self):
        msg = [ 'Inventory Queries:',
                '-> {0}'.format(self.classNameResolveError.nodename) ]
        msg.append(self.classNameResolveError._get_error_message())
        return msg


class ResolveError(InterpolationError):

    def __init__(self, reference, uri=None, context=None):
        super(ResolveError, self).__init__(msg=None)
        self.reference = reference

    def _get_error_message(self):
        msg = 'Cannot resolve {0}'.format(self.reference.join(REFERENCE_SENTINELS)) + self._add_context_and_uri()
        return [ msg ]


class ResolveErrorList(InterpolationError):
    def __init__(self):
        super(ResolveErrorList, self).__init__(msg=None)
        self.resolve_errors = []
        self._traceback = False

    def add(self, resolve_error):
        self.resolve_errors.append(resolve_error)

    def have_errors(self):
        return len(self.resolve_errors) > 0

    def _get_error_message(self):
        msgs = []
        for e in self.resolve_errors:
            msgs.extend(e._get_error_message())
        return msgs


class InvQueryError(InterpolationError):

    def __init__(self, query, resolveError, uri=None, context=None):
        super(InvQueryError, self).__init__(msg=None)
        self.query = query
        self.resolveError = resolveError
        self._traceback = self.resolveError._traceback

    def _get_error_message(self):
        msg1 = 'Failed inv query {0}'.format(self.query.join(EXPORT_SENTINELS)) + self._add_context_and_uri()
        msg2 = '-> {0}'.format(self.resolveError.nodename)
        msg3 = self.resolveError._get_error_message()
        return [ msg1, msg2, msg3 ]


class ParseError(InterpolationError):

    def __init__(self, msg, line, col, lineno, rc=posix.EX_DATAERR):
        super(ParseError, self).__init__(rc=rc, msg=None)
        self._err = msg
        self._line = line
        self._col = col
        self._lineno = lineno

    def _get_error_message(self):
        msg = [ 'Parse error: {0}'.format(self._line.join(EXPORT_SENTINELS)) + self._add_context_and_uri() ]
        msg.append('{0} at char {1}'.format(self._err, self._col - 1))
        return msg


class InfiniteRecursionError(InterpolationError):

    def __init__(self, context, ref, uri):
        super(InfiniteRecursionError, self).__init__(msg=None, tbFlag=False, uri=uri)
        self.context = context
        self.ref = ref

    def _get_error_message(self):
        msg = [ 'Infinite recursion: {0}'.format(self.ref.join(REFERENCE_SENTINELS)) + self._add_context_and_uri() ]
        return msg


class BadReferencesError(InterpolationError):

    def __init__(self, refs, context, uri):
        super(BadReferencesError, self).__init__(msg=None, context=context, uri=uri, tbFlag=False)
        self.refs = [ r.join(REFERENCE_SENTINELS) for r in refs ]

    def _get_error_message(self):
        msg = [ 'Bad references' + self._add_context_and_uri(),
                '   ' + ', '.join(self.refs) ]
        return msg


class TypeMergeError(InterpolationError):

    def __init__(self, value1, value2, uri):
        super(TypeMergeError, self).__init__(msg=None, uri=uri, tbFlag=False)
        self.type1 = value1.item_type_str()
        self.type2 = value2.item_type_str()

    def _get_error_message(self):
        msg = [ 'Cannot merge {0} over {1}'.format(self.type1, self.type2) + self._add_context_and_uri() ]
        return msg


class ExpressionError(InterpolationError):

    def __init__(self, msg, rc=posix.EX_DATAERR, tbFlag=True):
        super(ExpressionError, self).__init__(rc=rc, msg=None, tbFlag=tbFlag)
        self._error_msg = msg

    def _get_error_message(self):
        msg = [ 'Expression error: {0}'.format(self._error_msg) + self._add_context_and_uri() ]
        return msg


class ChangedConstantError(InterpolationError):

    def __init__(self, uri):
        super(ChangedConstantError, self).__init__(msg=None, uri=uri, tbFlag=False)

    def _get_error_message(self):
        msg = [ 'Attempt to change constant value' + self._add_context_and_uri() ]
        return msg


class MappingError(ReclassException):

    def __init__(self, msg, rc=posix.EX_DATAERR):
        super(MappingError, self).__init__(rc=rc, msg=msg)


class MappingFormatError(MappingError):

    def __init__(self, msg):
        super(MappingFormatError, self).__init__(msg)


class NameError(ReclassException):

    def __init__(self, msg, rc=posix.EX_DATAERR):
        super(NameError, self).__init__(rc=rc, msg=msg)


class InvalidClassnameError(NameError):

    def __init__(self, invalid_character, classname):
        super(InvalidClassnameError, self).__init__(msg=None)
        self._char = invalid_character
        self._classname = classname

    def _get_message(self):
        msg = "Invalid character '{0}' in class name '{1}'."
        return msg.format(self._char, self._classname)


class DuplicateNodeNameError(NameError):

    def __init__(self, storage, name, uri1, uri2):
        super(DuplicateNodeNameError, self).__init__(msg=None)
        self._storage = storage
        self._name = name
        self._uris = (uri1, uri2)

    def _get_message(self):
        msg = "{0}: Definition of node '{1}' in '{2}' collides with " \
              "definition in '{3}'. Nodes can only be defined once " \
              "per inventory."
        return msg.format(self._storage, self._name, self._uris[1], self._uris[0])


class MissingModuleError(ReclassException):

    def __init__(self, modname):
        msg = "Module %s is missing" % modname
        super(MissingModuleError, self).__init__(rc=posix.EX_DATAERR, msg=msg)
