# 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

'''
Module contains wrappers for test items that have been
loaded by the testlib :class:`testlib.loader.Loader`.
'''
import itertools

import log
import uid
from state import Status, Result

class TestCaseMetadata():
    def __init__(self, name, uid, path, result, status, suite_uid):
        self.name = name
        self.uid = uid
        self.path = path
        self.status = status
        self.result = result
        self.suite_uid = suite_uid


class TestSuiteMetadata():
    def __init__(self, name, uid, tags, path, status, result):
        self.name = name
        self.uid = uid
        self.tags = tags
        self.path = path
        self.status = status
        self.result = result


class LibraryMetadata():
    def __init__(self, name, result, status):
        self.name = name
        self.result = result
        self.status = status


class LoadedTestable(object):
    '''
    Base class for loaded test items.

    :property:`result` and :property:`status` setters
    notify testlib via the :func:`log_result` and :func:`log_status`
    of the updated status.
    '''
    def __init__(self, obj):
        self.obj = obj
        self.metadata = self._generate_metadata()

    @property
    def status(self):
        return self.metadata.status

    @status.setter
    def status(self, status):
        self.log_status(status)
        self.metadata.status = status

    @property
    def result(self):
        return self.metadata.result

    @result.setter
    def result(self, result):
        self.log_result(result)
        self.metadata.result = result

    @property
    def uid(self):
        return self.metadata.uid

    @property
    def name(self):
        return self.metadata.name

    @property
    def fixtures(self):
        return self.obj.fixtures

    @fixtures.setter
    def fixtures(self, fixtures):
        self.obj.fixtures = fixtures

    @property
    def runner(self):
        return self.obj.runner

    # TODO Change log to provide status_update, result_update for all types.
    def log_status(self, status):
        log.test_log.status_update(self, status)

    def log_result(self, result):
        log.test_log.result_update(self, result)

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


class LoadedTest(LoadedTestable):
    def __init__(self, test_obj, loaded_suite, path):
        self.parent_suite = loaded_suite
        self._path = path
        LoadedTestable.__init__(self, test_obj)

    def test(self, *args, **kwargs):
        self.obj.test(*args, **kwargs)

    def _generate_metadata(self):
        return TestCaseMetadata( **{
            'name':self.obj.name,
            'path': self._path,
            'uid': uid.TestUID(self._path,
                               self.obj.name,
                               self.parent_suite.name),
            'status': Status.Unscheduled,
            'result': Result(Result.NotRun),
            'suite_uid': self.parent_suite.metadata.uid
        })


class LoadedSuite(LoadedTestable):
    def __init__(self, suite_obj, path):
        self._path = path
        LoadedTestable.__init__(self, suite_obj)
        self.tests = self._wrap_children(suite_obj)

    def _wrap_children(self, suite_obj):
        return [LoadedTest(test, self, self.metadata.path)
                for test in suite_obj]

    def _generate_metadata(self):
        return TestSuiteMetadata( **{
            'name': self.obj.name,
            'tags':self.obj.tags,
            'path': self._path,
            'uid': uid.SuiteUID(self._path, self.obj.name),
            'status': Status.Unscheduled,
            'result': Result(Result.NotRun)
        })

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

    @property
    def tags(self):
        return self.metadata.tags


class LoadedLibrary(LoadedTestable):
    '''
    Wraps a collection of all loaded test suites and
    provides utility functions for accessing fixtures.
    '''
    def __init__(self, suites, global_fixtures):
        LoadedTestable.__init__(self, suites)
        self.global_fixtures = global_fixtures

    def _generate_metadata(self):
        return LibraryMetadata( **{
            'name': 'Test Library',
            'status': Status.Unscheduled,
            'result': Result(Result.NotRun)
        })

    def __iter__(self):
        '''
        :returns: an iterator over contained :class:`TestSuite` objects.
        '''
        return iter(self.obj)

    def all_fixture_tuples(self):
        return itertools.chain(
                self.global_fixtures,
                *(suite.fixtures for suite in self.obj))

    def all_fixtures(self):
        '''
        :returns: an interator overall all global, suite,
          and test fixtures
        '''
        return itertools.chain(itertools.chain(
                self.global_fixtures,
                *(suite.fixtures for suite in self.obj)),
            *(self.test_fixtures(suite) for suite in self.obj)
        )

    def test_fixtures(self, suite):
        '''
        :returns: an interator over all fixtures of each
          test contained in the given suite
        '''
        return itertools.chain(*(test.fixtures for test in suite))

    @property
    def fixtures(self):
        return self.global_fixtures

    @property
    def uid(self):
        return self.name

    @property
    def suites(self):
        return self.obj

    @suites.setter
    def suites(self, suites):
        self.obj = suites
