from abc import ABC
import typing_extensions

from experimaestro.core.types import ObjectType
import experimaestro
import io
from experimaestro.launchers import Launcher
from experimaestro.scheduler.base import Job

from experimaestro.scheduler.workspace import RunMode
from .context import (
    SerializationContext as SerializationContext,
    SerializedPath as SerializedPath,
    SerializedPathLoader as SerializedPathLoader,
)
from _typeshed import Incomplete
from collections.abc import Generator
from experimaestro.core.types import (
    DeprecatedAttribute as DeprecatedAttribute,
    ObjectType as ObjectType,
)
from experimaestro.utils import logger as logger
from functools import cached_property as cached_property
from pathlib import Path
from typing import (
    Any,
    Callable,
    ClassVar,
    Dict,
    List,
    Optional,
    Set,
    TypeVar,
    Union,
    overload,
)

T = TypeVar("T", bound="Config")

class Identifier:
    main: Incomplete
    sub: Incomplete
    def __init__(self, main: bytes, sub: Optional[bytes] = ...) -> None: ...
    def all(self): ...
    def state_dict(self): ...
    @staticmethod
    def from_state_dict(data: Union[Dict[str, str], str]): ...

def is_ignored(value): ...
def remove_meta(value): ...

class HashComputer:
    OBJECT_ID: bytes
    INT_ID: bytes
    FLOAT_ID: bytes
    STR_ID: bytes
    PATH_ID: bytes
    NAME_ID: bytes
    NONE_ID: bytes
    LIST_ID: bytes
    TASK_ID: bytes
    DICT_ID: bytes
    ENUM_ID: bytes
    def __init__(self) -> None: ...
    def identifier(self) -> Identifier: ...
    def update(self, value, subparam: bool = ..., myself: bool = ...): ...

def updatedependencies(
    dependencies, value: Config, path: List[str], taskids: Set[int]
): ...

class TaggedValue:
    value: Incomplete
    def __init__(self, value) -> None: ...

def add_to_path(p) -> Generator[None, None, None]: ...

class ConfigWalkContext:
    @property
    def path(self) -> None: ...
    def __init__(self) -> None: ...
    @property
    def task(self) -> None: ...
    def currentpath(self) -> Path: ...
    def push(self, key: str): ...

NOT_SET: Incomplete

class ConfigProcessing:
    recurse_task: Incomplete
    visited: Incomplete
    def __init__(self, recurse_task: bool = ...) -> None: ...
    def preprocess(self, config: Config): ...
    def postprocess(self, config: Config, values: Dict[str, Any]): ...
    def list(self, i: int): ...
    def map(self, k: str): ...
    def __call__(self, x): ...

class ConfigWalk(ConfigProcessing):
    context: Incomplete
    def __init__(self, context: ConfigWalkContext) -> None: ...
    def list(self, i: int): ...
    def map(self, k: str): ...

def getqualattr(module, qualname): ...

class ConfigInformation:
    LOADING: bool
    pyobject: Incomplete
    xpmtype: Incomplete
    values: Incomplete
    job: Job
    dependencies: Incomplete
    def __init__(self, pyobject: TypeConfig) -> None: ...
    def set_meta(self, value: Optional[bool]): ...
    @property
    def meta(self): ...
    def get(self, name): ...
    def set(self, k, v, bypass: bool = ...) -> None: ...
    def addtag(self, name, value) -> None: ...
    def xpmvalues(self, generated: bool = ...) -> Generator[Incomplete, None, None]: ...
    def tags(self): ...
    def validate(self) -> None: ...
    def seal(self, context: ConfigWalkContext): ...
    @property
    def identifier(self) -> Identifier: ...
    def dependency(self): ...
    def updatedependencies(
        self,
        dependencies: Set["experimaestro.dependencies.Dependency"],
        path: List[str],
        taskids: Set[int],
    ): ...
    def submit(self, workspace, launcher, run_mode: RunMode = ...) -> TaskOutput: ...
    def outputjson(self, out: io.TextIOBase, context: SerializationContext): ...
    def __json__(self): ...
    def serialize(self, save_directory: Path): ...
    @staticmethod
    def deserialize(
        path: Union[str, Path, SerializedPathLoader], as_instance: bool = ...
    ) -> Config: ...
    @overload
    @staticmethod
    def fromParameters(
        definitions: List[Dict],
        as_instance: bool = ...,
        save_directory: Optional[Path] = ...,
    ) -> TypeConfig: ...
    @overload
    @staticmethod
    def fromParameters(
        definitions: List[Dict],
        as_instance: bool = ...,
        save_directory: Optional[Path] = ...,
    ) -> Config: ...

    class FromPython(ConfigWalk):
        objects: Incomplete
        def __init__(self, context: ConfigWalkContext) -> None: ...
        def preprocess(self, config: Config): ...
        def postprocess(self, config: Config, values: Dict[str, Any]): ...

    def fromConfig(self, context: ConfigWalkContext): ...
    def add_dependencies(self, *dependencies) -> None: ...

def clone(v): ...
def cache(fn, name: str): ...

class TypeConfig:
    __xpmtype__: ObjectType
    __xpm__: Incomplete
    def __init__(self, **kwargs) -> None: ...
    def tag(self, name, value): ...
    def __eq__(self, other): ...
    def __arguments__(self): ...
    def tags(self): ...
    def add_dependencies(self, *dependencies): ...
    def instance(self, context: ConfigWalkContext = ...) -> T: ...
    def submit(
        self,
        *,
        workspace: Incomplete | None = ...,
        launcher: Incomplete | None = ...,
        run_mode: RunMode = ...,
        pre: List[Task] = []
    ): ...
    def stdout(self): ...
    def stderr(self): ...
    @property
    def job(self): ...
    @property
    def jobpath(self): ...
    def copy(self): ...

@typing_extensions.dataclass_transform(kw_only_default=True)
class Config:
    __xpmtype__: ClassVar[ObjectType]
    __xpm__: ConfigInformation
    @classmethod
    def __getxpmtype__(cls) -> ObjectType: ...
    def __getnewargs_ex__(self): ...
    @classmethod
    def c(cls, **kwargs) -> T: ...
    def __new__(cls, *args, __xpmobject__: bool = ..., **kwargs) -> T: ...
    def __validate__(self) -> None: ...
    def __post_init__(self) -> None: ...
    def __json__(self): ...
    def __identifier__(self) -> Identifier: ...

class Task(Config):
    __tags__: Dict[str, str]
    def execute(self) -> None: ...

class Proxy:
    def __unwrap__(self) -> Any: ...

class ItemAccessor:
    key: Incomplete
    def __init__(self, key: Any) -> None: ...
    def toJSON(self): ...
    def get(self, value): ...

class AttrAccessor:
    key: Incomplete
    default: Incomplete
    def __init__(self, key: Any, default: Any) -> None: ...
    def get(self, value): ...
    def toJSON(self): ...

class Serialized:
    value: Incomplete
    def __init__(self, value) -> None: ...
    def toJSON(self): ...

class SerializedConfig:
    pyobject: Incomplete
    loader: Incomplete
    def __init__(self, pyobject: Config, loader) -> None: ...

class TaskOutputInfo:
    task: Incomplete
    value: Incomplete
    path: Incomplete
    serialized: Incomplete
    def __init__(self, task: Task) -> None: ...
    @property
    def identifier(self): ...
    @property
    def job(self): ...
    def tags(self): ...
    def stdout(self): ...
    def stderr(self): ...
    def wait(self): ...

class TaskOutput(Proxy):
    __xpm__: Incomplete
    def __init__(self, value: Any, task: Union[Task, TaskOutputInfo]) -> None: ...
    def __getitem__(self, key: Any): ...
    def __getattr__(self, key: str, default: Incomplete | None = ...) -> Any: ...
    def __unwrap__(self): ...
    def __call__(self, *args, **kwargs): ...

class SerializedTaskOutput(TaskOutput):
    def __init__(
        self, value, serialized: SerializedConfig, task: Task, path: List[Any]
    ) -> None: ...
    def __getitem__(self, key: Any): ...
    def __getattr__(self, key: str, default: Incomplete | None = ...) -> Any: ...

def copyconfig(config_or_output: Union[Config, TaskOutput], **kwargs): ...
def setmeta(config: Config, flag: bool): ...

class TypeConfig:
    def __validate__(self):
        pass
