""" LimitlessLED pipeline. """

import logging
import threading
import time

from limitlessled import Color

_LOGGER = logging.getLogger(__name__)


class PipelineQueue(threading.Thread):
    """ Pipeline queue. """

    def __init__(self, queue, event):
        """ Initialize pipeline queue.

        :param queue: Read from this queue.
        :param event: Read from this event.
        """
        super(PipelineQueue, self).__init__()
        self._queue = queue
        self._event = event

    def run(self):
        """ Run the pipeline queue.

        The pipeline queue will run forever.
        """
        while True:
            self._event.clear()
            self._queue.get().run(self._event)


class Stage(object):
    """ Stage. """

    def __init__(self, name, args, kwargs):
        """ Initialize stage.

        :param name: Name of stage.
        :param args: Positional arguments.
        :param kwargs: Keyword arguments.
        """
        self.name = name
        self.args = args
        self.kwargs = kwargs

    def __str__(self):
        """ String representation of Stage.

        :returns: String
        """
        args = []
        if len(self.args) > 0:
            args += ['{}'.format(a) for a in self.args]
        if len(self.kwargs) > 0:
            args += ["{}={}".format(k, v) for k, v in self.kwargs.items()]
        return '{}({})'.format(self.name, ', '.join(args))


class Pipeline(object):
    """ Pipeline.

    Pipelines are built by linking together a series
    of stages. Upon execution, the pipeline applies
    each stage to the given LimitlessLED group.
    """

    def __init__(self):
        """ Initialize pipeline.

        Stage methods are dynamically initialized
        since they all follow the same pattern.
        """
        self._pipe = []
        self._group = None
        stages = ['on', 'off', 'color', 'transition', 'flash', 'callback',
                  'repeat', 'brightness', 'wait', 'temperature', 'white',
                  'white_up', 'white_down', 'red_up', 'red_down',
                  'green_up', 'green_down', 'blue_up', 'blue_down',
                  'night_light', 'link', 'unlink']
        for name in stages:
            self._add_stage(name)

    @property
    def pipe(self):
        """ Pipe property. """
        return self._pipe

    @property