# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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.

"""
Thread task executor.
"""

import Queue
import threading

import sys

from aria.utils import imports, exceptions

from .base import BaseExecutor


class ThreadExecutor(BaseExecutor):
    """
    Thread task executor.

    It's easier writing tests using this executor rather than the full-blown sub-process executor.

    Note: This executor is incapable of running plugin operations.
    """

    def __init__(self, pool_size=1, close_timeout=5, *args, **kwargs):
        super(ThreadExecutor, self).__init__(*args, **kwargs)
        self._stopped = False
        self._close_timeout = close_timeout
        self._queue = Queue.Queue()
        self._pool = []
        for i in range(pool_size):
            name = 'ThreadExecutor-{0:d}'.format(i+1)
            thread = threading.Thread(target=self._processor, name=name)
            thread.daemon = True
            thread.start()
            self._pool.append(thread)

    def _execute(self, ctx):
        self._queue.put(ctx)

    def close(self):
        self._stopped = True
        for thread in self._pool:
            if self._close_timeout is None:
                thread.join()
            else:
                thread.join(self._close_timeout)

    def _processor(self):
        while not self._stopped:
            try:
                ctx = self._queue.get(timeout=1)
                self._task_started(ctx)
                try:
                    task_func = imports.load_attribute(ctx.task.function)
                    arguments = dict(arg.unwrapped for arg in ctx.task.arguments.itervalues())
                    task_func(ctx=ctx, **arguments)
                    self._task_succeeded(ctx)
                except BaseException as e:
                    self._task_failed(ctx,
                                      exception=e,
                                      traceback=exceptions.get_exception_as_string(*sys.exc_info()))
            # Daemon threads
            except BaseException as e:
                pass
