
# Generated by OTF2 Template Engine

import _otf2

from .enums import Type


def parse(registry, union_value, type_id):
@otf2 for entry in Type.entries if entry.type:
    if type_id == Type.@@entry.suffix@@:
        return union_value.@@entry.type.lower@@
@otf2 endfor
@otf2 for entry in MappingType.entries:
    if type_id == Type.@@entry.def.ref_upper@@:
        return registry.@@entry.def.ref_lower@@s[union_value.@@entry.def.ref_lname@@Ref]
@otf2 endfor
    raise TypeError("Unexpected type.")


def make(registry, value, type_id, writer=None):
    """
    :param registry:
    :param value:
    :param otf2.Type type_id:
    :param writer: If set, the string value will be written. Otherwise just added to the registry
    :return:
    """
    # values are expected to be int, float, or a Definition subclass
    union = _otf2.AttributeValue()
    if type_id == Type.UINT8:
        union.uint8 = int(value)
    elif type_id == Type.UINT16:
        union.uint16 = int(value)
    elif type_id == Type.UINT32:
        union.uint32 = int(value)
    elif type_id == Type.UINT64:
        union.uint64 = int(value)
    elif type_id == Type.INT8:
        union.int8 = int(value)
    elif type_id == Type.INT16:
        union.int16 = int(value)
    elif type_id == Type.INT32:
        union.int32 = int(value)
    elif type_id == Type.INT64:
        union.int64 = int(value)
    elif type_id == Type.FLOAT:
        union.float32 = float(value)
    elif type_id == Type.DOUBLE:
        union.float64 = float(value)
    elif type_id == Type.STRING:
        union.stringRef = registry.strings.get_ref(value, writer)
@otf2 for entry in MappingType.entries if entry.name != 'OTF2_MAPPING_STRING':
    elif type_id == Type.@@entry.suffix@@:
        union.@@entry.def.ref_lname@@Ref = value._ref
@otf2 endfor
    else:
        raise TypeError("Unexpected type id given")

    return union


class AttributeValue(object):
    def __init__(self, value, type_id):
        self.value = value
        self.type_id = type_id

    def as_otf2(self, registry, writer=None):
        return make(registry, self.value, self.type_id, writer)

    def set(self, value, type_id=None):
        # TODO Ideally we would want to check if the value is compatible with the type,
        # but that would introduce a circular dependency to the definitions
        self.value = value
        if type_id is not None:
            self.type_id = type_id

    @classmethod
    def _construct(cls, registry, union_value, type_id):
        return cls(parse(registry, union_value, type_id), type_id)
