# Copyright (C) 2017 Apple Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1.  Redistributions of source code must retain the above copyright
#     notice, this list of conditions and the following disclaimer.
# 2.  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.
#
# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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.

import logging
import math
import os
import signal
import time
import threading

_log = logging.getLogger(__name__)


class Timeout(object):

    thread_exception = RuntimeError('Timeout originates from a different thread')
    _process_to_timeout_map = {}

    class TimeoutData(object):

        def __init__(self, alarm_time, handler):
            self.alarm_time = alarm_time
            self.handler = handler
            self.thread_id = threading.current_thread().ident

    @staticmethod
    def default_handler(signum, frame):
        raise RuntimeError('Timeout alarm was triggered')

    @staticmethod
    def current():
        result = Timeout._process_to_timeout_map.get(os.getpid(), [])
        if not result:
            return None
        if result[0].thread_id != threading.current_thread().ident:
            _log.critical('Using both alarms and threading in the same process, this is unsupported')
            raise Timeout.thread_exception
        return result[0]

    def __init__(self, seconds=1, handler=None):
        if seconds == 0:
            raise RuntimeError('Cannot have a timeout of 0 seconds')

        if isinstance(handler, BaseException):
            exception = handler

            def exception_handler(signum, frame):
                raise exception

            handler = exception_handler

        self._timeout = seconds
        self._handler = handler if handler else Timeout.default_handler
        self.data = None

    @staticmethod
    def _bind_timeout_data_to_alarm(data):
        def handler(signum, frame):
            assert signum == signal.SIGALRM
            if data.thread_id != threading.current_thread().ident:
                raise Timeout.thread_exception
            data.handler(signum, frame)

        current_time = time.time()
        if data.alarm_time <= current_time:
            handler(signal.SIGALRM, None)

        signal.signal(signal.SIGALRM, handler)
        signal.alarm(int(math.ceil(data.alarm_time - current_time)))

    def __enter__(self):
        signal.alarm(0)  # Imiediatly disable the alarm so we aren't interupted.
        self.data = Timeout.TimeoutData(time.time() + self._timeout, self._handler)
        current_timeout = Timeout.current()

        # Another timeout is more urgent.
        if current_timeout and current_timeout.alarm_time < self.data.alarm_time:
            for i in xrange(len(Timeout._process_to_timeout_map[os.getpid()]) - 1):
                if self.data.alarm_time < Timeout._process_to_timeout_map[os.getpid()][i + 1].alarm_time:
                    Timeout._process_to_timeout_map[os.getpid()].insert(i, self.data)
                    break
            Timeout._process_to_timeout_map[os.getpid()].append(self.data)

        # This is the most urgent timeout
        else:
            Timeout._process_to_timeout_map[os.getpid()] = [self.data] + Timeout._process_to_timeout_map.get(os.getpid(), [])

        Timeout._bind_timeout_data_to_alarm(Timeout.current())
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        signal.alarm(0)  # Imiediatly disable the alarm so we aren't interupted.

        if not Timeout._process_to_timeout_map[os.getpid()]:
            raise RuntimeError('No timeout registered')
        Timeout._process_to_timeout_map[os.getpid()].remove(self.data)
        self.data = None

        if Timeout._process_to_timeout_map[os.getpid()]:
            Timeout._bind_timeout_data_to_alarm(Timeout.current())
