# Copyright (c) 2017 Mark D. Hill and David A. Wood
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met: redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer;
# redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution;
# neither the name of the copyright holders nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Authors: Sean Wilson

'''
Helper classes for writing tests with this test library.
'''
from collections import MutableSet, OrderedDict

import difflib
import errno
import os
import Queue
import re
import shutil
import stat
import subprocess
import tempfile
import threading
import time
import traceback

#TODO Tear out duplicate logic from the sandbox IOManager
def log_call(logger, command, *popenargs, **kwargs):
    '''
    Calls the given process and automatically logs the command and output.

    If stdout or stderr are provided output will also be piped into those
    streams as well.

    :params stdout: Iterable of items to write to as we read from the
        subprocess.

    :params stderr: Iterable of items to write to as we read from the
        subprocess.
    '''
    if isinstance(command, str):
        cmdstr = command
    else:
        cmdstr = ' '.join(command)

    logger_callback = logger.trace
    logger.trace('Logging call to command: %s' % cmdstr)

    stdout_redirect = kwargs.get('stdout', tuple())
    stderr_redirect = kwargs.get('stderr', tuple())

    if hasattr(stdout_redirect, 'write'):
        stdout_redirect = (stdout_redirect,)
    if hasattr(stderr_redirect, 'write'):
        stderr_redirect = (stderr_redirect,)

    kwargs['stdout'] = subprocess.PIPE
    kwargs['stderr'] = subprocess.PIPE
    p = subprocess.Popen(command, *popenargs, **kwargs)

    def log_output(log_callback, pipe, redirects=tuple()):
        # Read iteractively, don't allow input to fill the pipe.
        for line in iter(pipe.readline, ''):
            for r in redirects:
                r.write(line)
            log_callback(line.rstrip())

    stdout_thread = threading.Thread(target=log_output,
                           args=(logger_callback, p.stdout, stdout_redirect))
    stdout_thread.setDaemon(True)
    stderr_thread = threading.Thread(target=log_output,
                           args=(logger_callback, p.stderr, stderr_redirect))
    stderr_thread.setDaemon(True)

    stdout_thread.start()
    stderr_thread.start()

    retval = p.wait()
    stdout_thread.join()
    stderr_thread.join()
    # Return the return exit code of the process.
    if retval != 0:
        raise subprocess.CalledProcessError(retval, cmdstr)

# lru_cache stuff (Introduced in python 3.2+)
# Renamed and modified to cacheresult
class _HashedSeq(list):
    '''
    This class guarantees that hash() will be called no more than once per
    element. This is important because the cacheresult() will hash the key
    multiple times on a cache miss.

    .. note:: From cpython 3.7
    '''

    __slots__ = 'hashvalue'

    def __init__(self, tup, hash=hash):
        self[:] = tup
        self.hashvalue = hash(tup)

    def __hash__(self):
        return self.hashvalue

def _make_key(args, kwds, typed,
             kwd_mark = (object(),),
             fasttypes = {int, str, frozenset, type(None)},
             tuple=tuple, type=type, len=len):
    '''
    Make a cache key from optionally typed positional and keyword arguments.
    The key is constructed in a way that is flat as possible rather than as
    a nested structure that would take more memory.  If there is only a single
    argument and its data type is known to cache its hash value, then that
    argument is returned without a wrapper. This saves space and improves
    lookup speed.

    .. note:: From cpython 3.7
    '''
    key = args
    if kwds:
        key += kwd_mark
        for item in kwds.items():
            key += item
    if typed:
        key += tuple(type(v) for v in args)
        if kwds:
            key += tuple(type(v) for v in kwds.values())
    elif len(key) == 1 and type(key[0]) in fasttypes:
        return key[0]
    return _HashedSeq(key)


def cacheresult(function, typed=False):
    '''
    :param typed: If typed is True, arguments of different types will be
        cached separately. I.e. f(3.0) and f(3) will be treated as distinct
        calls with distinct results.

    .. note:: From cpython 3.7
    '''
    sentinel = object()          # unique object used to signal cache misses
    make_key = _make_key         # build a key from the function arguments
    cache = {}
    def wrapper(*args, **kwds):
        # Simple caching without ordering or size limit
        key = _make_key(args, kwds, typed)
        result = cache.get(key, sentinel)
        if result is not sentinel:
            return result
        result = function(*args, **kwds)
        cache[key] = result
        return result
    return wrapper

class OrderedSet(MutableSet):
    '''
    Maintain ordering of insertion in items to the set with quick iteration.

    http://code.activestate.com/recipes/576694/
    '''

    def __init__(self, iterable=None):
        self.end = end = []
        end += [None, end, end]         # sentinel node for doubly linked list
        self.map = {}                   # key --> [key, prev, next]
        if iterable is not None:
            self |= iterable

    def __len__(self):
        return len(self.map)

    def __contains__(self, key):
        return key in self.map

    def add(self, key):
        if key not in self.map:
            end = self.end
            curr = end[1]
            curr[2] = end[1] = self.map[key] = [key, curr, end]

    def update(self, keys):
        for key in keys:
            self.add(key)

    def discard(self, key):
        if key in self.map:
            key, prev, next = self.map.pop(key)
            prev[2] = next
            next[1] = prev

    def __iter__(self):
        end = self.end
        curr = end[2]
        while curr is not end:
            yield curr[0]
            curr = curr[2]

    def __reversed__(self):
        end = self.end
        curr = end[1]
        while curr is not end:
            yield curr[0]
            curr = curr[1]

    def pop(self, last=True):
        if not self:
            raise KeyError('set is empty')
        key = self.end[1][0] if last else self.end[2][0]
        self.discard(key)
        return key

    def __repr__(self):
        if not self:
            return '%s()' % (self.__class__.__name__,)
        return '%s(%r)' % (self.__class__.__name__, list(self))

    def __eq__(self, other):
        if isinstance(other, OrderedSet):
            return len(self) == len(other) and list(self) == list(other)
        return set(self) == set(other)

def absdirpath(path):
    '''
    Return the directory component of the absolute path of the given path.
    '''
    return os.path.dirname(os.path.abspath(path))

joinpath = os.path.join

def mkdir_p(path):
    '''
    Same thing as mkdir -p

    https://stackoverflow.com/a/600612
    '''
    try:
        os.makedirs(path)
    except OSError as exc:  # Python >2.5
        if exc.errno == errno.EEXIST and os.path.isdir(path):
            pass
        else:
            raise


class FrozenSetException(Exception):
    '''Signals one tried to set a value in a 'frozen' object.'''
    pass


class AttrDict(object):
    '''Object which exposes its own internal dictionary through attributes.'''
    def __init__(self, dict_={}):
        self.update(dict_)

    def __getattr__(self, attr):
        dict_ = self.__dict__
        if attr in dict_:
            return dict_[attr]
        raise AttributeError('Could not find %s attribute' % attr)

    def __setattr__(self, attr, val):
        self.__dict__[attr] = val

    def __iter__(self):
        return iter(self.__dict__)

    def __getitem__(self, item):
        return self.__dict__[item]

    def update(self, items):
        self.__dict__.update(items)


class FrozenAttrDict(AttrDict):
    '''An AttrDict whose attributes cannot be modified directly.'''
    __initialized = False
    def __init__(self, dict_={}):
        super(FrozenAttrDict, self).__init__(dict_)
        self.__initialized = True

    def __setattr__(self, attr, val):
        if self.__initialized:
            raise FrozenSetException(
                        'Cannot modify an attribute in a FozenAttrDict')
        else:
            super(FrozenAttrDict, self).__setattr__(attr, val)

    def update(self, items):
        if self.__initialized:
            raise FrozenSetException(
                        'Cannot modify an attribute in a FozenAttrDict')
        else:
            super(FrozenAttrDict, self).update(items)


class InstanceCollector(object):
    '''
    A class used to simplify collecting of Classes.

    >> instance_list = collector.create()
    >> # Create a bunch of classes which call collector.collect(self)
    >> # instance_list contains all instances created since
    >> # collector.create was called
    >> collector.remove(instance_list)
    '''
    def __init__(self):
        self.collectors = []

    def create(self):
        collection = []
        self.collectors.append(collection)
        return collection

    def remove(self, collector):
        self.collectors.remove(collector)

    def collect(self, instance):
        for col in self.collectors:
            col.append(instance)


def append_dictlist(dict_, key, value):
    '''
    Append the `value` to a list associated with `key` in `dict_`.
    If `key` doesn't exist, create a new list in the `dict_` with value in it.
    '''
    list_ = dict_.get(key, [])
    list_.append(value)
    dict_[key] = list_


class ExceptionThread(threading.Thread):
    '''
    Wrapper around a python :class:`Thread` which will raise an
    exception on join if the child threw an unhandled exception.
    '''
    def __init__(self, *args, **kwargs):
        threading.Thread.__init__(self, *args, **kwargs)
        self._eq = Queue.Queue()

    def run(self, *args, **kwargs):
        try:
            threading.Thread.run(self, *args, **kwargs)
            self._eq.put(None)
        except:
            tb = traceback.format_exc()
            self._eq.put(tb)

    def join(self, *args, **kwargs):
        threading.Thread.join(*args, **kwargs)
        exception = self._eq.get()
        if exception:
            raise Exception(exception)


def _filter_file(fname, filters):
    with open(fname, "r") as file_:
        for line in file_:
            for regex in filters:
                if re.match(regex, line):
                    break
            else:
                yield line


def _copy_file_keep_perms(source, target):
    '''Copy a file keeping the original permisions of the target.'''
    st = os.stat(target)
    shutil.copy2(source, target)
    os.chown(target, st[stat.ST_UID], st[stat.ST_GID])


def _filter_file_inplace(fname, filters):
    '''
    Filter the given file writing filtered lines out to a temporary file, then
    copy that tempfile back into the original file.
    '''
    reenter = False
    (_, tfname) = tempfile.mkstemp(text=True)
    with open(tfname, 'w') as tempfile_:
        for line in _filter_file(fname, filters):
            tempfile_.write(line)

    # Now filtered output is into tempfile_
    _copy_file_keep_perms(tfname, fname)


def diff_out_file(ref_file, out_file, logger, ignore_regexes=tuple()):
    '''Diff two files returning the diff as a string.'''

    if not os.path.exists(ref_file):
        raise OSError("%s doesn't exist in reference directory"\
                                     % ref_file)
    if not os.path.exists(out_file):
        raise OSError("%s doesn't exist in output directory" % out_file)

    _filter_file_inplace(out_file, ignore_regexes)
    _filter_file_inplace(ref_file, ignore_regexes)

    #try :
    (_, tfname) = tempfile.mkstemp(text=True)
    with open(tfname, 'r+') as tempfile_:
        try:
            log_call(logger, ['diff', out_file, ref_file], stdout=tempfile_)
        except OSError:
            # Likely signals that diff does not exist on this system. fallback
            # to difflib
            with open(out_file, 'r') as outf, open(ref_file, 'r') as reff:
                diff = difflib.unified_diff(iter(reff.readline, ''),
                                            iter(outf.readline, ''),
                                            fromfile=ref_file,
                                            tofile=out_file)
                return ''.join(diff)
        except subprocess.CalledProcessError:
            tempfile_.seek(0)
            return ''.join(tempfile_.readlines())
        else:
            return None

class Timer():
    def __init__(self):
        self.restart()

    def restart(self):
        self._start = self.timestamp()
        self._stop = None

    def stop(self):
        self._stop = self.timestamp()
        return self._stop - self._start

    def runtime(self):
        return self._stop - self._start

    def active_time(self):
        return self.timestamp() - self._start

    @staticmethod
    def timestamp():
        return time.time()