"""Loading and saving functions."""
from pathlib import Path
from typing import Any, IO, Union

import yatiml

from ymmsl.component import Component, Ports
from ymmsl.configuration import Configuration, PartialConfiguration
from ymmsl.document import Document
from ymmsl.execution import (
        ExecutionModel, Implementation, ResourceRequirements, MPICoresResReq,
        MPINodesResReq, ThreadedResReq)
from ymmsl.settings import Settings
from ymmsl.identity import Identifier, Reference
from ymmsl.model import Conduit, Model, ModelReference


_classes = (
        PartialConfiguration, Component, Conduit, Configuration, Document,
        ExecutionModel, Identifier, Implementation, Model, ModelReference,
        MPICoresResReq, MPINodesResReq, Ports, Reference, ResourceRequirements,
        Settings, ThreadedResReq)


_load = yatiml.load_function(*_classes)


def load(source: Union[str, Path, IO[Any]]) -> PartialConfiguration:
    """Loads a yMMSL document from a string or a file.

    Args:
        source: A string containing yMMSL data, a pathlib Path to a
                file containing yMMSL data, or an open file-like
                object containing from which yMMSL data can be read.

    Returns:
        A PartialConfiguration object corresponding to the input data.

    """
    # This wrapper is just here to render the documentation.
    return _load(source)


_dump = yatiml.dumps_function(*_classes)


def dump(config: PartialConfiguration) -> str:
    """Converts a yMMSL configuration to a string containing YAML.

    Args:
        config: The configuration to be saved to yMMSL.

    Returns:
        A yMMSL YAML description of the given document.

    """
    # This wrapper is just here to render the documentation.
    return _dump(config)


_save = yatiml.dump_function(*_classes)


def save(
        config: PartialConfiguration, target: Union[str, Path, IO[Any]]
        ) -> None:
    """Saves a yMMSL configuration to a file.

    Args:
        config: The configuration to save to yMMSL.
        target: The file to save to, either as a string containing a
            path, as a pathlib Path object, or as an open file-like
            object.

    """
    # This wrapper is just here to render the documentation.
    _save(config, target)
