# -*- coding: utf-8 -*-

"""Set of CIM v2 ontology type definitions.

necessary to describe software. This module has not been touched for a
long time, and needs replacement.

"""


def component_base():
    """Base class for software component properties, whether a top level
    model, or a specific piece of code known as a component.

    In software terms, a component is a discrete set of code that takes
    input data and generates output data. Components may or may not have
    scientific descriptions.

    """
    return {
        "type": "class",
        "base": None,
        "is_abstract": True,
        "pstr": ("{}", ("name",)),
        "properties": [
            (
                "citations",
                "linked_to(shared.citation)",
                "0.N",
                "Set of pertinent citations.",
            ),
            (
                "canonical_id",
                "str",
                "0.1",
                "Vocabulary identifier, where this framework/component "
                "description was constructed via a controlled vocabulary.",
            ),
            (
                "description",
                "str",
                "0.1",
                "Textural description of component.",
            ),
            ("long_name", "str", "0.1", "Long name for component."),
            ("name", "str", "1.1", "Short name of component."),
            (
                "responsible_parties",
                "shared.responsibility",
                "0.N",
                "People or organisations responsible for providing this "
                "information.",
            ),
            (
                "development_history",
                "software.development_path",
                "0.1",
                "History of the development of this component.",
            ),
            (
                "release_date",
                "time.date_time",
                "0.1",
                "The date of publication of the component code (as opposed "
                "to the date of publication of the metadata document, or the "
                "date of deployment of the model).",
            ),
            (
                "repository",
                "shared.online_resource",
                "0.1",
                "Location of code for this component.",
            ),
            ("version", "str", "0.1", "Version identifier."),
        ],
    }


def implementation():
    """Implementation information for a software framework/component,
    whether a top level model, or a specific piece of code known as a
    'component'.

    In software terms, a software framework/component is a discrete set
    of code that takes input data and generates output data. Software
    frameworks/components may or may not have scientific descriptions.

    """
    return {
        "type": "class",
        "base": None,
        "is_abstract": False,
        "pstr": ("{}", ("name",)),
        "properties": [
            (
                "citations",
                "linked_to(shared.citation)",
                "0.N",
                "Set of pertinent citations.",
            ),
            (
                "canonical_id",
                "str",
                "0.1",
                "Vocabulary identifier, where this framework/component "
                "description was constructed via a controlled vocabulary.",
            ),
            (
                "description",
                "str",
                "0.1",
                "Textural description of framework/component.",
            ),
            (
                "development_history",
                "software.development_path",
                "0.1",
                "History of the development of this framework/component.",
            ),
            ("long_name", "str", "0.1", "Long name for framework/component."),
            ("name", "str", "1.1", "Short name of framework/component."),
            (
                "release_date",
                "datetime",
                "0.1",
                "The date of publication of the framework/component code.",
            ),
            (
                "repository",
                "shared.online_resource",
                "0.1",
                "Location of code for this framework/component.",
            ),
            ("version", "str", "0.1", "Version identifier."),
        ],
    }


def composition():
    """Describes how component variables are coupled together either
    to/from other SoftwareComponents or external data files. The
    variables specified by a component's composition must be owned by
    that component, or a  child of that component; child components
    cannot couple together parent variables.

    # FIXME: THIS CLASS IS BELIEVED TO BE OBSOLETE AND WILL BE
    REVIEWED/REPLACED IN THE NEXT VERSION

    """
    return {
        "type": "class",
        "base": None,
        "is_abstract": False,
        "properties": [
            ("couplings", "str", "0.N", "#FIXME."),
            ("description", "str", "0.1", "#FIXME."),
        ],
    }


def development_path():
    """Describes the software development path for this
    model/component."""
    return {
        "type": "class",
        "base": None,
        "is_abstract": False,
        "properties": [
            (
                "consortium_name",
                "str",
                "0.1",
                "If model/component is developed as part of a consortium, "
                "provide consortium name.",
            ),
            (
                "creators",
                "shared.responsibility",
                "0.N",
                "Those responsible for creating this component.",
            ),
            (
                "was_developed_in_house",
                "bool",
                "1.1",
                "Model or component was mostly developed in house.",
            ),
            (
                "funding_sources",
                "shared.responsibility",
                "0.N",
                "The entities that funded this software component.",
            ),
            ("previous_version", "str", "0.1", "Name of a previous version."),
        ],
    }


def entry_point():
    """Describes a function or subroutine of a SoftwareComponent. BFG
    will use these EntryPoints to define a schedule of subroutine calls
    for a coupled model. Currently, a very basic schedule can be
    approximated by using the 'proceeds' and 'follows' attributes,
    however a more complete system is required for full BFG
    compatibility. Every EntryPoint can have a set of arguments
    associated with it. These reference (previously defined) variables.

    # FIXME: THIS CLASS IS BELIEVED TO BE OBSOLETE AND WILL BE
    REVIEWED/REPLACED IN THE NEXT VERSION

    """
    return {
        "type": "class",
        "base": None,
        "is_abstract": False,
        "properties": [("name", "str", "0.1", "#FIXME.")],
    }


def gridspec():
    """Fully defines the computational grid used.

    # FIXME: THIS CLASS IS BELIEVED TO BE OBSOLETE AND WILL BE
    REVIEWED/REPLACED IN THE NEXT VERSION

    """
    return {
        "type": "class",
        "base": None,
        "is_abstract": False,
        "properties": [("description", "str", "1.1", "Textural description.")],
    }


def software_component():
    """An embedded piece of software that does not normally function as
    a standalone model (although it may be used standalone in a test
    harness)."""
    return {
        "type": "class",
        "base": "software.component_base",
        "is_abstract": False,
        "is_document": True,
        "properties": [
            ("composition", "software.composition", "0.1", "#FIXME."),
            (
                "connection_points",
                "software.variable",
                "0.N",
                "The set of data entities which are available for I/O and/or "
                "coupling.",
            ),
            (
                "coupling_framework",
                "software.coupling_framework",
                "0.1",
                "The coupling framework that this entire component conforms "
                "to.",
            ),
            ("dependencies", "software.entry_point", "0.N", "#FIXME."),
            (
                "grid",
                "software.gridspec",
                "0.1",
                "A reference to the grid that is used by this component.",
            ),
            (
                "language",
                "software.programming_language",
                "0.1",
                "Language the component is written in.",
            ),
            (
                "license",
                "str",
                "0.1",
                "The license held by this piece of software.",
            ),
            (
                "sub_components",
                "linked_to(software.software_component)",
                "0.N",
                "Internal software sub-components of this component.",
            ),
            (
                "depends_on",
                "linked_to(software.software_component)",
                "0.N",  # added dch/ssw 1016-0804
                "The software components whose outputs are inputs to this "
                "software component.",
            ),
            # Would like to think about making this a stand-alone document
        ],
    }


def variable():
    """An instance of a model software variable which may be prognostic
    or diagnostic, and which is available as a connection to other
    software components. Note that these variables may only exist within
    the software workflow as interim quantities or coupling endpoints.
    Input and output variables will be a subset of these software
    variables.

    # FIXME: THIS CLASS IS BELIEVED TO BE OBSOLETE AND WILL BE
    REVIEWED/REPLACED IN THE NEXT VERSION

    """
    return {
        "type": "class",
        "base": None,
        "is_abstract": False,
        "properties": [
            (
                "description",
                "str",
                "0.1",
                "Description of how the variable is being used in the s/w.",
            ),
            ("name", "str", "1.1", "Short name for the variable."),
            (
                "is_prognostic",
                "bool",
                "1.1",
                "Whether or not prognostic or diagnostic.",
            ),
        ],
    }
