"""Program ``faust send`` used to send events to agents and topics."""
import asyncio
import random
from typing import Any
from faust.types import CodecArg, K, RecordMetadata, V
from .base import AppCommand, argument, option

__all__ = ['send']


class send(AppCommand):
    """Send message to agent/topic."""

    topic: Any
    key: K
    key_serializer: CodecArg
    value: V
    value_serializer: CodecArg
    repeat: int
    min_latency: float
    max_latency: float

    options = [
        option('--key-type', '-K',
               help='Name of model to serialize key into.'),
        option('--key-serializer',
               help='Override default serializer for key.'),
        option('--value-type', '-V',
               help='Name of model to serialize value into.'),
        option('--value-serializer',
               help='Override default serializer for value.'),
        option('--key', '-k',
               help='String value for key (use json if model).'),
        option('--partition', type=int,
               help='Specific partition to send to.'),
        option('--repeat', '-r', type=int, default=1,
               help='Send message n times.'),
        option('--min-latency', type=float, default=0.0,
               help='Minimum delay between sending.'),
        option('--max-latency', type=float, default=0.0,
               help='Maximum delay between sending.'),

        argument('entity'),
        argument('value', default=None, required=False),
    ]

    async def run(self,
                  entity: str,
                  value: str,
                  *args: Any,
                  key: str = None,
                  key_type: str = None,
                  key_serializer: str = None,
                  value_type: str = None,
                  value_serializer: str = None,
                  partition: int = 1,
                  timestamp: float = None,
                  repeat: int = 1,
                  min_latency: float = 0.0,
                  max_latency: float = 0.0,
                  **kwargs: Any) -> Any:
        """Send message to topic/agent/channel."""
        if key is not None:
            key = self.to_key(key_type, key)
        if value is not None:
            value = self.to_value(value_type, value)
        topic = self.to_topic(entity)
        for i in range(repeat):
            self.carp(f'k={key!r} v={value!r} -> {topic!r}...')
            fut_send_complete = await topic.send(
                key=key,
                value=value,
                partition=partition,
                timestamp=timestamp,
                key_serializer=key_serializer,
                value_serializer=value_serializer,
            )
            meta: RecordMetadata = await fut_send_complete
            self.say(self.dumps(meta._asdict()))
            if i and max_latency:
                await asyncio.sleep(random.uniform(min_latency, max_latency))
        await self.app.producer.stop()
