"""Classes for handling modeling protocols.
"""


class Step:
    """A single step in a :class:`Protocol`.

       This class describes a generic step in a modeling protocol. In most
       cases, a more specific subclass should be used, such as
       :class:`TemplateSearchStep`, :class:`ModelingStep`, or
       :class:`ModelSelectionStep`.

       :param input_data: Any objects that this step takes as input.
              Any individual :class:`modelcif.data.Data` object (such as
              a template structure, target sequence, alignment, or model
              coordinates) can be given here, or a group of such objects (as a
              :class:`modelcif.data.DataGroup` object) can be passed.
       :type input_data: :class:`modelcif.data.DataGroup`
             or :class:`modelcif.data.Data`
       :param output_data: Any objects that this step creates as output,
              similarly to ``input_data``.
       :type output_data: :class:`modelcif.data.DataGroup`
             or :class:`modelcif.data.Data`
       :param str name: A short name for this step.
       :param str details: Longer description of this step.
       :param software: The software that was employed in this modeling step.
       :type software: :class:`modelcif.Software`
             or :class:`modelcif.SoftwareGroup`
    """
    method_type = "other"

    def __init__(self, input_data, output_data, name=None, details=None,
                 software=None):
        self.input_data, self.output_data = input_data, output_data
        self.name, self.details, self.software = name, details, software


class TemplateSearchStep(Step):
    """A modeling protocol step that searches for templates.
       See :class:`Step` for more details."""
    method_type = "template search"


class TemplateSelectionStep(Step):
    """A modeling protocol step that selects one or more templates.
       See :class:`Step` for more details."""
    method_type = "template selection"


class TargetTemplateAlignmentStep(Step):
    """A modeling protocol step that creates a target-template alignment.
       See :class:`Step` for more details."""
    method_type = "target-template alignment"


class CoevolutionMSAStep(Step):
    """A modeling protocol step that creates a coevolution multiple sequence
       alignment. See :class:`Step` for more details."""
    method_type = "coevolution MSA"


class ContactPredictionStep(Step):
    """A modeling protocol step that predicts contacts.
       See :class:`Step` for more details."""
    method_type = "contact prediction"


class ModelingStep(Step):
    """A modeling protocol step that generates model coordinates.
       See :class:`Step` for more details."""
    method_type = "modeling"


class ModelSelectionStep(Step):
    """A modeling protocol step that filters candidates to select models.
       See :class:`Step` for more details."""
    method_type = "model selection"


class ModelRefinementStep(Step):
    """A modeling protocol step that refines models.
       See :class:`Step` for more details."""
    method_type = "model refinement"


class ModelAssessmentStep(Step):
    """A modeling protocol step that performs model quality assessment.
       See :class:`Step` for more details."""
    method_type = "model quality assessment"


class BackboneGenerationStep(Step):
    """A modeling protocol step that generates backbone coordinates for
       protein design.
       See :class:`Step` for more details."""
    method_type = "backbone generation"


class SequenceDesignStep(Step):
    """A modeling protocol step that generates sequences for protein design.
       This includes inverse folding.
       See :class:`Step` for more details."""
    method_type = "sequence design"


class StructureValidationStep(Step):
    """A modeling protocol step that assesses designed sequences with
       their modeled structures.
       See :class:`Step` for more details."""
    method_type = "structure validation"


class EnergyEstimateStep(Step):
    """A modeling protocol step that performs an energy estimate.
       See :class:`Step` for more details."""
    method_type = "energy estimate"


class ExperimentalValidationStep(Step):
    """A modeling protocol step that conducts experimental validation.
       See :class:`Step` for more details."""
    method_type = "experimental validation"


class Protocol:
    """A modeling protocol.
       Each protocol consists of a number of protocol steps."""
    def __init__(self):
        #: All modeling steps (:class:`Step` objects)
        self.steps = []
