from typing import Dict, List, Optional, Tuple
from . import eaf, eah, property, trigger

from typing import overload
import ioh.iohcpp

class AbstractWatcher(Logger):
    def watch(self, arg0: property.AbstractProperty) -> None: ...

class AbstractLogger(Logger):
    def __init__(self, triggers: List[trigger.Trigger], properties: List[property.AbstractProperty]) -> None: ... 
    def watch(self, arg0: property.AbstractProperty) -> None: ...

class Analyzer(AbstractWatcher):
    def __init__(self, triggers: List[trigger.Trigger] = ..., additional_properties: List[property.AbstractProperty] = ..., root: Path = ..., folder_name: str = ..., algorithm_name: str = ..., algorithm_info: str = ..., store_positions: bool = ...) -> None: ...
    def add_experiment_attribute(self, arg0: str, arg1: str) -> None: ...
    @overload
    def add_run_attributes(self, arg0: str, arg1: float) -> None: ...
    @overload
    def add_run_attributes(self, arg0: object, arg1: str) -> None: ...
    @overload
    def add_run_attributes(self, arg0: object, arg1: List[str]) -> None: ...
    def set_experiment_attributes(self, arg0: Dict[str,str]) -> None: ...
    def set_run_attribute(self, arg0: str, arg1: float) -> None: ...
    def set_run_attributes(self, arg0: Dict[str,float]) -> None: ...
    @overload
    def watch(self, arg0: property.AbstractProperty) -> None: ...
    @overload
    def watch(self, arg0: object, arg1: str) -> None: ...
    @overload
    def watch(self, arg0: object, arg1: List[str]) -> None: ...
    @property
    def output_directory(self) -> Path: ...

class Combine(Logger):
    @overload
    def __init__(self, loggers: List[Logger]) -> None: ...
    @overload
    def __init__(self, logger: Logger) -> None: ...
    def append(self, arg0: Logger) -> None: ...

class EAF(Logger):
    def __init__(self) -> None: ...
    def at(self, arg0: str, arg1: int, arg2: int, arg3: int, arg4: int) -> List[eaf.RunPoint]: ...
    @property
    def data(self) -> Dict[str,Dict[int,Dict[int,Dict[int,Dict[int,List[eaf.RunPoint]]]]]]: ...

class EAH(Logger):
    @overload
    def __init__(self, error_min: float, error_max: float, error_buckets: int, evals_min: int, evals_max: int, evals_buckets: int) -> None: ...
    @overload
    def __init__(self, error_scale: eah.LinearRealScale, eval_scale: eah.LinearIntegerScale) -> None: ...
    @overload
    def __init__(self, error_scale: eah.Log2RealScale, eval_scale: eah.Log2IntegerScale) -> None: ...
    @overload
    def __init__(self, error_scale: eah.Log10RealScale, eval_scale: eah.Log10IntegerScale) -> None: ...
    def at(self, arg0: int, arg1: int, arg2: int, arg3: int) -> List[List[bool]]: ...
    @property
    def data(self) -> Dict[int,Dict[int,Dict[int,Dict[int,List[List[bool]]]]]]: ...
    @property
    def error_range(self) -> eah.RealScale: ...
    @property
    def eval_range(self) -> eah.IntegerScale: ...
    @property
    def size(self) -> Tuple[int,int,int,int]: ...

class FlatFile(AbstractWatcher):
    def __init__(self, triggers: List[trigger.Trigger], properties: List[property.AbstractProperty], filename: str = ..., output_directory: Path = ..., separator: str = ..., comment: str = ..., no_value: str = ..., end_of_line: str = ..., repeat_header: bool = ..., store_positions: bool = ..., common_header_titles: List[str] = ...) -> None: ...
    @overload
    def watch(self, arg0: property.AbstractProperty) -> None: ...
    @overload
    def watch(self, arg0: object, arg1: str) -> None: ...
    @overload
    def watch(self, arg0: object, arg1: List[str]) -> None: ...
    @property
    def filename(self) -> str: ...
    @property
    def output_directory(self) -> str: ...

class Logger:
    def __init__(self, *args, **kwargs) -> None: ...
    def add_trigger(self, arg0: trigger.Trigger) -> None: ...
    def attach_problem(self, arg0: ioh.iohcpp.MetaData) -> None: ...
    def attach_suite(self, arg0: str) -> None: ...
    def call(self, arg0: ioh.iohcpp.LogInfo) -> None: ...
    def log(self, arg0: ioh.iohcpp.LogInfo) -> None: ...
    def reset(self) -> None: ...
    @property
    def problem(self) -> ioh.iohcpp.MetaData: ...

class Path:
    def __init__(self, arg0: str) -> None: ...

class Store(AbstractWatcher):
    def __init__(self, triggers: List[trigger.Trigger], properties: List[property.AbstractProperty]) -> None: ...
    def at(self, arg0: str, arg1: int, arg2: int, arg3: int, arg4: int, arg5: int) -> Dict[str,Optional[float]]: ...
    def data(self) -> Dict[str,Dict[int,Dict[int,Dict[int,Dict[int,Dict[int,Dict[str,Optional[float]]]]]]]]: ...
    @overload
    def watch(self, arg0: property.AbstractProperty) -> None: ...
    @overload
    def watch(self, arg0: object, arg1: str) -> None: ...
    @overload
    def watch(self, arg0: object, arg1: List[str]) -> None: ...
