"""
mbed SDK
Copyright (c) 2011-2016 ARM Limited

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Author: Przemyslaw Wirkus <Przemyslaw.Wirkus@arm.com>
"""

import pkg_resources  # part of setuptools
from sys import stdout
from mbed_host_tests.host_tests_runner.mbed_base import Mbed


class HostTestResults(object):
    """! Test results set by host tests """

    def enum(self, **enums):
        return type('Enum', (), enums)

    def __init__(self):
        self.TestResults = self.enum(
            RESULT_SUCCESS = 'success',
            RESULT_FAILURE = 'failure',
            RESULT_ERROR = 'error',
            RESULT_END = 'end',
            RESULT_UNDEF = 'undefined', # Rather for debug purpose
            RESULT_TIMEOUT = 'timeout',
            RESULT_IOERR_COPY = "ioerr_copy",
            RESULT_IOERR_DISK = "ioerr_disk",
            RESULT_IO_SERIAL = 'ioerr_serial',
            RESULT_NO_IMAGE = 'no_image',
            RESULT_NOT_DETECTED = "not_detected",
            RESULT_MBED_ASSERT = "mbed_assert",
            RESULT_PASSIVE = "passive",
            RESULT_BUILD_FAILED = 'build_failed',
            RESULT_SYNC_FAILED = 'sync_failed'
        )

        # Magically creates attributes in this class corresponding
        # to RESULT_ elements in self.TestResults enum
        for attr in self.TestResults.__dict__:
            if attr.startswith('RESULT_'):
                setattr(self, attr, self.TestResults.__dict__[attr])

        # Indexes of this list define string->int mapping between
        # actual strings with results
        self.TestResultsList = [
            self.TestResults.RESULT_SUCCESS,
            self.TestResults.RESULT_FAILURE,
            self.TestResults.RESULT_ERROR,
            self.TestResults.RESULT_END,
            self.TestResults.RESULT_UNDEF,
            self.TestResults.RESULT_TIMEOUT,
            self.TestResults.RESULT_IOERR_COPY,
            self.TestResults.RESULT_IOERR_DISK,
            self.TestResults.RESULT_IO_SERIAL,
            self.TestResults.RESULT_NO_IMAGE,
            self.TestResults.RESULT_NOT_DETECTED,
            self.TestResults.RESULT_MBED_ASSERT,
            self.TestResults.RESULT_PASSIVE,
            self.TestResults.RESULT_BUILD_FAILED,
            self.TestResults.RESULT_SYNC_FAILED
        ]

    def get_test_result_int(self, test_result_str):
        """! Maps test result string to unique integer """
        if test_result_str in self.TestResultsList:
            return self.TestResultsList.index(test_result_str)
        return -1

    def __getitem__(self, test_result_str):
        """! Returns numerical result code """
        return self.get_test_result_int(test_result_str)


class Test(HostTestResults):
    """ Base class for host test's test runner
    """
    def __init__(self, options):
        """ ctor
        """
        HostTestResults.__init__(self)
        self.mbed = Mbed(options)

    def run(self):
        """ Test runner for host test. This function will start executing
            test and forward test result via serial port to test suite
        """
        pass

    def setup(self):
        """! Setup and check if configuration for test is correct.
        @details This function can for example check if serial port is already opened
        """
        pass

    def notify(self, msg):
        """! On screen notification function
        @param msg Text message sent to stdout directly
        """
        stdout.write(msg)
        stdout.flush()

    def print_result(self, result):
        """! Test result unified printing function
        @param result Should be a member of HostTestResults.RESULT_* enums
        """
        self.notify("{{%s}}\n"% result)
        self.notify("{{%s}}\n"% self.RESULT_END)

    def finish(self):
        """ dctor for this class, finishes tasks and closes resources
        """
        pass

    def get_hello_string(self):
        """ Hello string used as first print
        """
        pkg = 'mbed-host-tests'
        version = pkg_resources.require(pkg)[0].version
        return "host test executor ver. " + version


class DefaultTestSelectorBase(Test):
    """! Test class with serial port initialization
    @details This is a base for other test selectors, initializes
    """
    def __init__(self, options):
        Test.__init__(self, options=options)
