# Copyright 2019 SKA South Africa
#
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

from typing import Text, Union, Iterator, Optional, overload
import socket

import spead2
from spead2 import _PybindStr

class Heap(object):
    def __init__(self, flavour: spead2.Flavour) -> None: ...
    @property
    def flavour(self) -> spead2.Flavour: ...
    @property
    def repeat_pointers(self) -> bool: ...
    @repeat_pointers.setter
    def repeat_pointers(self, value: bool) -> None: ...
    def add_item(self, item: spead2.Item) -> None: ...
    def add_descriptor(self, descriptor: spead2.Descriptor) -> None: ...
    def add_start(self) -> None: ...
    def add_end(self) -> None: ...

class PacketGenerator(object):
    def __init__(self, heap: Heap, cnt: int, max_packet_size: int) -> None: ...
    def __iter__(self) -> Iterator[bytes]: ...

class StreamConfig(object):
    DEFAULT_MAX_PACKET_SIZE: int = ...
    DEFAULT_MAX_HEAPS: int = ...
    DEFAULT_BURST_SIZE: int = ...
    DEFAULT_BURST_RATE_RATIO: float = ...

    def __init__(self, max_packet_size: int = ..., rate: float = ...,
                 burst_size: int = ..., max_heaps: int = ...,
                 burst_rate_ratio: float = ...) -> None: ...

    @property
    def max_packet_size(self) -> int: ...
    @max_packet_size.setter
    def max_packet_size(self, value: int) -> None: ...

    @property
    def rate(self) -> float: ...
    @rate.setter
    def rate(self, value: float) -> None: ...

    @property
    def burst_size(self) -> int: ...
    @burst_size.setter
    def burst_size(self, value: int) -> None: ...

    @property
    def max_heaps(self) -> int: ...
    @max_heaps.setter
    def max_heaps(self, value: int) -> None: ...

    @property
    def burst_rate_ratio(self) -> float: ...
    @burst_rate_ratio.setter
    def burst_rate_ratio(self, float) -> None: ...

    @property
    def burst_rate(self) -> float: ...

class _Stream(object):
    def set_cnt_sequence(self, next: int, step: int) -> None: ...

class _SyncStream(_Stream):
    def send_heap(self, heap: Heap, cnt: int = ...) -> None: ...

class _UdpStream(object):
    DEFAULT_BUFFER_SIZE: int = ...

class UdpStream(_UdpStream, _SyncStream):
    @overload
    def __init__(self, thread_pool: spead2.ThreadPool,
                 hostname: _PybindStr, port: int,
                 config: StreamConfig,
                 buffer_size: int, socket: socket.socket) -> None: ...
    @overload
    def __init__(self, thread_pool: spead2.ThreadPool,
                 hostname: _PybindStr, port: int,
                 config: StreamConfig = ...,
                 buffer_size: int = ..., interface_address: _PybindStr = ...) -> None: ...
    @overload
    def __init__(self, thread_pool: spead2.ThreadPool,
                 hostname: _PybindStr, port: int,
                 config: StreamConfig,
                 ttl: int) -> None: ...
    @overload
    def __init__(self, thread_pool: spead2.ThreadPool,
                 hostname: _PybindStr, port: int,
                 config: StreamConfig,
                 ttl: int, interface_address: _PybindStr) -> None: ...
    @overload
    def __init__(self, thread_pool: spead2.ThreadPool,
                 hostname: _PybindStr, port: int,
                 config: StreamConfig,
                 ttl: int, interface_index: int) -> None: ...
    @overload
    def __init__(self, thread_pool: spead2.ThreadPool,
                 socket: socket.socket, hostname: _PybindStr, port: int,
                 config: StreamConfig = ...) -> None: ...

class _UdpIbvStream(object):
    DEFAULT_BUFFER_SIZE: int = ...
    DEFAULT_MAX_POLL: int = ...

class UdpIbvStream(_UdpIbvStream, _SyncStream):
    def __init__(self, thread_pool: spead2.ThreadPool,
                 multicast_group: _PybindStr, port: int,
                 config: StreamConfig,
                 interface_address: _PybindStr,
                 buffer_size: int = ..., ttl: int = ...,
                 comp_vector: int = ..., max_pool: int = ...) -> None: ...

class _TcpStream(object):
    DEFAULT_BUFFER_SIZE: int = ...

class TcpStream(_TcpStream, _SyncStream):
    @overload
    def __init__(self, thread_pool: spead2.ThreadPool, socket: socket.socket,
                 config: StreamConfig = ...) -> None: ...
    @overload
    def __init__(self, thread_pool: spead2.ThreadPool,
                 hostname: _PybindStr, port: int,
                 config: StreamConfig = ...,
                 buffer_size: int = ..., interface_address: _PybindStr = ...) -> None: ...

class _BytesStream(object):
    def getvalue(self) -> bytes: ...

class BytesStream(_BytesStream, _SyncStream):
    def __init__(self, thread_pool: spead2.ThreadPool,
                 config: StreamConfig = ...) -> None: ...

class _InprocStream(object):
    @property
    def queue(self) -> spead2.InprocQueue: ...

class InprocStream(_InprocStream, _SyncStream):
    def __init__(self, thread_pool: spead2.ThreadPool, queue: spead2.InprocQueue,
                 config: StreamConfig = ...) -> None: ...

class HeapGenerator(object):
    def __init__(self, item_group: spead2.ItemGroup, descriptor_frequency: Optional[int] = None,
                 flavour: spead2.Flavour = spead2.Flavour()) -> None: ...
    def add_to_heap(self, heap: Heap, descriptors: str = ..., data: str = ...) -> Heap: ...
    def get_heap(self, descriptors: str = ..., data: str = ...) -> Heap: ...
    def get_start(self) -> Heap: ...
    def get_end(self) -> Heap: ...

class ItemGroup(spead2.ItemGroup, HeapGenerator):
    def __init__(self, descriptor_frequency: Optional[int] = None,
                 flavour: spead2.Flavour = ...) -> None: ...
