from simphony_metaparser.flags import NoDefault

from simphony_metaparser.nodes import (
    Ontology, CUBADataType, CUDSItem, FixedProperty,
    VariableProperty)


def trivial_ontology():
    ontology = Ontology()
    ontology.data_types.extend([
        CUBADataType(name="CUBA.CUBA_DATA_ONE",
                     type="string"),
        CUBADataType(name="CUBA.CUBA_DATA_TWO",
                     type="string")
    ])
    ontology.root_cuds_item = CUDSItem(name="CUBA.CUDS_ROOT")
    ontology.root_cuds_item.children.extend([
        CUDSItem(name="CUBA.CUDS_C1", parent=ontology.root_cuds_item),
        CUDSItem(name="CUBA.CUDS_C2", parent=ontology.root_cuds_item)]
    )

    return ontology


def trivial_ontology_keywords_output():
    return """# code auto-generated by the
# simphony-metadata/scripts/generate.py script.
from collections import namedtuple

import numpy
import uuid  # noqa

ATTRIBUTES = ["name", "definition", "key", "shape", "length", "dtype"]
Keyword = namedtuple("Keyword", ATTRIBUTES)

KEYWORDS = {
    'CUBA_DATA_ONE':
    Keyword(
        name='CubaDataOne',
        definition='',
        key='CUBA_DATA_ONE',
        shape=[],
        length=None,
        dtype=numpy.str),
    'CUBA_DATA_TWO':
    Keyword(
        name='CubaDataTwo',
        definition='',
        key='CUBA_DATA_TWO',
        shape=[],
        length=None,
        dtype=numpy.str),
    'CUDS_C1':
    Keyword(
        name='CUDSC1',
        definition='',
        key='CUDS_C1',
        shape=[1],
        length=None,
        dtype=None),
    'CUDS_C2':
    Keyword(
        name='CUDSC2',
        definition='',
        key='CUDS_C2',
        shape=[1],
        length=None,
        dtype=None),
    'CUDS_ROOT':
    Keyword(
        name='CUDSRoot',
        definition='',
        key='CUDS_ROOT',
        shape=[1],
        length=None,
        dtype=None),
}
"""


def complex_ontology():
    ontology = Ontology()
    cuds_item = CUDSItem(name="CUBA.CUDS_ITEM")
    cuds_item.properties["data"] = FixedProperty(
        name="data",
        scope="CUBA.SYSTEM",
        default=NoDefault,
        item=cuds_item
    )

    cuds_item.properties["CUBA.UID"] = VariableProperty(
        name="CUBA.UID",
        scope="CUBA.SYSTEM",
        shape=[1],
        default=NoDefault,
        item=cuds_item
    )

    cuds_component = CUDSItem(name="CUBA.CUDS_COMPONENT",
                              parent=cuds_item)
    cuds_item.children.append(cuds_component)
    cuds_component.properties["CUBA.NAME"] = VariableProperty(
        name="CUBA.NAME",
        scope="CUBA.USER",
        shape=[1],
        default="",
        item=cuds_component
    )

    physics_equation = CUDSItem(name="CUBA.PHYSICS_EQUATION",
                                parent=cuds_component)
    cuds_component.children.append(physics_equation)

    gravity_model = CUDSItem(name="CUBA.GRAVITY_MODEL",
                             parent=physics_equation)
    physics_equation.children.append(gravity_model)
    gravity_model.properties["models"] = FixedProperty(
        name="models",
        scope="CUBA.USER",
        default=["CUBA.MESOSCOPIC", "CUBA.CONTINUUM"],
        item=gravity_model
    )
    gravity_model.properties["CUBA.ACCELERATION"] = \
        VariableProperty(name="CUBA.ACCELERATION",
                         scope="CUBA.USER",
                         shape=[1],
                         default=[0, 0, 0],
                         item=gravity_model)

    ontology.root_cuds_item = cuds_item

    return ontology


def ontology_with_reimplemented_variable_properties():
    ontology = Ontology()
    cuds_item = CUDSItem(name="CUBA.CUDS_ITEM")
    cuds_item.properties["data"] = FixedProperty(
        name="data",
        scope="CUBA.SYSTEM",
        default=NoDefault,
        item=cuds_item
    )

    cuds_item.properties["CUBA.UID"] = VariableProperty(
        name="CUBA.UID",
        scope="CUBA.SYSTEM",
        shape=[1],
        default=NoDefault,
        item=cuds_item
    )

    cuds_component = CUDSItem(name="CUBA.CUDS_COMPONENT",
                              parent=cuds_item)
    cuds_item.children.append(cuds_component)
    cuds_component.properties["CUBA.NAME"] = VariableProperty(
        name="CUBA.NAME",
        scope="CUBA.USER",
        shape=[1],
        default="",
        item=cuds_component
    )

    # -------
    material_relation = CUDSItem(name="CUBA.MATERIAL_RELATION",
                                 parent=cuds_component)
    cuds_component.children.append(material_relation)
    material_relation.properties["CUBA.MATERIAL"] = \
        VariableProperty(name="CUBA.MATERIAL",
                         scope="CUBA.USER",
                         shape=[None],
                         default=[],
                         item=material_relation)

    interatomic_potential = CUDSItem(name="CUBA.INTERATOMIC_POTENTIAL",
                                     parent=material_relation)

    material_relation.children.append(interatomic_potential)
    pair_potential = CUDSItem(name="CUBA.PAIR_POTENTIAL",
                              parent=interatomic_potential)
    interatomic_potential.children.append(pair_potential)

    pair_potential.properties["CUBA.MATERIAL"] = \
        VariableProperty(name="CUBA.MATERIAL",
                         scope="CUBA.USER",
                         shape=[2],
                         default=NoDefault,
                         item=pair_potential)

    ontology.root_cuds_item = cuds_item
    return ontology


def complex_ontology_output_gravity_model():
    return '''from simphony.core import Default  # noqa
from simphony.cuds import meta_validation
from simphony.core.cuba import CUBA
from .physics_equation import PhysicsEquation


class GravityModel(PhysicsEquation):
    """
    """
    cuba_key = CUBA.GRAVITY_MODEL

    def __init__(self, acceleration=Default, name=Default):
        super(GravityModel, self).__init__(name=name)
        self._init_models()
        self._init_acceleration(acceleration)

    @classmethod
    def supported_parameters(cls):
        try:
            base_params = super(GravityModel, cls).supported_parameters()
        except AttributeError:
            base_params = ()
        return tuple(set((CUBA.ACCELERATION, ) + base_params))

    def _init_models(self):
        self._models = self._default_models()  # noqa

    @property
    def models(self):
        return self._models

    def _default_models(self):
        return ['CUBA.MESOSCOPIC', 'CUBA.CONTINUUM']  # noqa

    def _init_acceleration(self, value):
        if value is Default:
            value = self._default_acceleration()

        self.acceleration = value

    @property
    def acceleration(self):
        return self.data[CUBA.ACCELERATION]

    @acceleration.setter
    def acceleration(self, value):
        value = self._validate_acceleration(value)
        self.data[CUBA.ACCELERATION] = value

    def _validate_acceleration(self, value):
        value = meta_validation.cast_data_type(value, 'ACCELERATION')
        meta_validation.check_valid_shape(value, [1], 'ACCELERATION')
        meta_validation.validate_cuba_keyword(value, 'ACCELERATION')
        return value

    def _default_acceleration(self):
        return [0, 0, 0]
'''
