"""Essential tooling for implementing DataLad commands

This module provides the advanced command base class
:class:`ValidatedInterface`, for implementing commands with uniform argument
validation and structured error reporting.

Beyond that, any further components necessary to implement command are imported
in this module to offer a one-stop-shop experience. This includes
``build_doc``, ``datasetmethod``, and ``eval_results``, among others.

.. currentmodule:: datalad_next.commands
.. autosummary::
   :toctree: generated

   CommandResult
   CommandResultStatus
   status.StatusResult
"""
from __future__ import annotations

from typing import Dict

from datalad.interface.base import (
    Interface,
    build_doc,
)
from datalad.interface.results import get_status_dict
from datalad.interface.utils import generic_result_renderer
from datalad.interface.base import eval_results
from datalad.support.param import Parameter

from datalad_next.constraints import (
    EnsureCommandParameterization,
    ParameterConstraintContext,
)
from datalad_next.datasets import datasetmethod
from .results import (
    CommandResult,
    CommandResultStatus,
)

class ValidatedInterface(Interface):
    """Alternative base class for commands with uniform parameter validation

    .. note::
       This interface is a draft. Usage is encouraged, but future changes
       are to be expected.

    Commands derived from the traditional ``Interface`` class have no built-in
    input parameter validation beyond CLI input validation of individual
    parameters. Consequently, each command must perform custom parameter
    validation, which often leads to complex boilerplate code that is largely
    unrelated to the purpose of a particular command.

    This class is part of a framework for uniform parameter validation,
    regardless of the target API (Python, CLI, GUI). The implementation of
    a command's ``__call__`` method can focus on the core purpose of the
    command, while validation and error handling can be delegated elsewhere.

    A validator for all individual parameters and the joint-set of all
    parameters can be provided through the :meth:`get_parameter_validator`
    method.

    To transition a command from ``Interface`` to ``ValidatedInterface``,
    replace the base class declaration and declare a ``_validator_`` class
    member. Any ``constraints=`` declaration for ``Parameter`` instances
    should either be removed, or moved to the corresponding entry in
    ``_validator_``.
    """
    _validator_: EnsureCommandParameterization | None = None

    @classmethod
    def get_parameter_validator(cls) -> EnsureCommandParameterization | None:
        """Returns a validator for the entire parameter set of a command

        If parameter validation shall be performed, this method must return an
        instance of
        :class:`~datalad_next.constraints.EnsureCommandParameterization`.
        All parameters will be passed through this validator, and only the its
        output will be passed to the underlying command's ``__call__`` method.

        Consequently, the core implementation of a command only needs to
        support the output values of the validators declared by itself.

        Factoring out input validation, normalization, type coercion etc. into
        a dedicated component also makes it accessible for upfront validation
        and improved error reporting via the different DataLad APIs.

        If a command does not implement parameter validation in this fashion,
        this method must return ``None``.

        The default implementation returns the ``_validator_`` class member.
        """
        return cls._validator_
