from typing import Optional, Union, Tuple, Sequence, TextIO, List


class Control:
    enter:  Control
    exit:   Control
    cancel: Control


class Level:
    info: Level
    assertion: Level
    warning  : Level

class Scope:
    def __init__(self, name: str): ...
    def __iadd__(self, rhs: Scope): ...
    def to_dict(self) -> dict: ...

    executed: int
    errors: int
    warnings: int
    children: List[Scope]
    tests = []
    cancelled: bool
    parent: Optional[Scope]
    name: str
    description: Optional[str]

    def append_test(self, param: dict): ...


class Reporter:

    def should_print(self, level = Level.info, condition = 1) -> bool: ...

    def critical(self, file: str, line: int, mode: Control, function: Optional[str]): ...

    def loop    (self, file: str, line: int, mode: Control): ...

    def ranged  (self, file: str, line: int, mode: Control, condition_or_length: Union[bool, int],
                 range_info: Optional[Tuple[str, str, str, str]],
                 range_info_values: Optional[Tuple[str, int, str, str]]): ...

    def call(self, file: str, line: int, mode: Control, condition: bool, function: Optional[str]): ...
    
    def log(self, file: str, line: int, message: str): ...
    def checkpoint(self, file: str, line: int): ...

    def message(self, file: str, line: int, level: Level, condition: bool, message: str): ...
    def plain  (self, file: str, line: int, level: Level, condition: bool, description: str): ...

    def equal    (self, file: str, line: int, level: Level, condition: bool, lhs: str, rhs: str, lhs_val: Optional[str], rhs_val: Optional[str]): ...
    def not_equal(self, file: str, line: int, level: Level, condition: bool, lhs: str, rhs: str, lhs_val: Optional[str], rhs_val: Optional[str]): ...

    def predicate(self, file: str, line: int, level: Level, condition: bool, function: str, args: Sequence[str],
                  function_val: Optional[str], args_val: Optional[Sequence[str]]): ...

    def ge     (self, file: str, line: int, level: Level, condition: bool, lhs: str, rhs: str, lhs_val: Optional[str], rhs_val: Optional[str]): ...
    def le     (self, file: str, line: int, level: Level, condition: bool, lhs: str, rhs: str, lhs_val: Optional[str], rhs_val: Optional[str]): ...
    def greater(self, file: str, line: int, level: Level, condition: bool, lhs: str, rhs: str, lhs_val: Optional[str], rhs_val: Optional[str]): ...
    def lesser (self, file: str, line: int, level: Level, condition: bool, lhs: str, rhs: str, lhs_val: Optional[str], rhs_val: Optional[str]): ...

    def close         (self, file: str, line: int, level: Level, condition: bool, lhs: str, rhs: str, tolerance: str, lhs_val: Optional[str], rhs_val: Optional[str], tolerance_val: Optional[str]): ...
    def close_relative(self, file: str, line: int, level: Level, condition: bool, lhs: str, rhs: str, tolerance: str, lhs_val: Optional[str], rhs_val: Optional[str], tolerance_val: Optional[str]): ...

    def report(self, file: str, line: int, condition: bool): ...

    hrf_sink: Optional[TextIO]
    print_level : str
    json_sink: Optional[TextIO]

    __scope_stack = List[Scope]

    @property
    def current_scope(self) -> Scope: ...