
# Generated by OTF2 Template Engine

from six import string_types

import _otf2

from .enums import Type


def parse(registry, union_value, type_id):
    if type_id == Type.UINT8:
        return union_value.uint8
    if type_id == Type.UINT16:
        return union_value.uint16
    if type_id == Type.UINT32:
        return union_value.uint32
    if type_id == Type.UINT64:
        return union_value.uint64
    if type_id == Type.INT8:
        return union_value.int8
    if type_id == Type.INT16:
        return union_value.int16
    if type_id == Type.INT32:
        return union_value.int32
    if type_id == Type.INT64:
        return union_value.int64
    if type_id == Type.FLOAT:
        return union_value.float32
    if type_id == Type.DOUBLE:
        return union_value.float64
    if type_id == Type.STRING:
        return registry.strings[union_value.stringRef]
    if type_id == Type.ATTRIBUTE:
        return registry.attributes[union_value.attributeRef]
    if type_id == Type.LOCATION:
        return registry.locations[union_value.locationRef]
    if type_id == Type.REGION:
        return registry.regions[union_value.regionRef]
    if type_id == Type.GROUP:
        return registry.groups[union_value.groupRef]
    if type_id == Type.METRIC:
        return registry.metrics[union_value.metricRef]
    if type_id == Type.COMM:
        return registry.comms[union_value.commRef]
    if type_id == Type.PARAMETER:
        return registry.parameters[union_value.parameterRef]
    if type_id == Type.RMA_WIN:
        return registry.rma_wins[union_value.rmaWinRef]
    if type_id == Type.SOURCE_CODE_LOCATION:
        return registry.source_code_locations[union_value.sourceCodeLocationRef]
    if type_id == Type.CALLING_CONTEXT:
        return registry.calling_contexts[union_value.callingContextRef]
    if type_id == Type.INTERRUPT_GENERATOR:
        return registry.interrupt_generators[union_value.interruptGeneratorRef]
    if type_id == Type.IO_FILE:
        return registry.io_files[union_value.ioFileRef]
    if type_id == Type.IO_HANDLE:
        return registry.io_handles[union_value.ioHandleRef]
    if type_id == Type.LOCATION_GROUP:
        return registry.location_groups[union_value.locationGroupRef]
    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)
    elif type_id == Type.ATTRIBUTE:
        union.attributeRef = value._ref
    elif type_id == Type.LOCATION:
        union.locationRef = value._ref
    elif type_id == Type.REGION:
        union.regionRef = value._ref
    elif type_id == Type.GROUP:
        union.groupRef = value._ref
    elif type_id == Type.METRIC:
        union.metricRef = value._ref
    elif type_id == Type.COMM:
        union.commRef = value._ref
    elif type_id == Type.PARAMETER:
        union.parameterRef = value._ref
    elif type_id == Type.RMA_WIN:
        union.rmaWinRef = value._ref
    elif type_id == Type.SOURCE_CODE_LOCATION:
        union.sourceCodeLocationRef = value._ref
    elif type_id == Type.CALLING_CONTEXT:
        union.callingContextRef = value._ref
    elif type_id == Type.INTERRUPT_GENERATOR:
        union.interruptGeneratorRef = value._ref
    elif type_id == Type.IO_FILE:
        union.ioFileRef = value._ref
    elif type_id == Type.IO_HANDLE:
        union.ioHandleRef = value._ref
    elif type_id == Type.LOCATION_GROUP:
        union.locationGroupRef = value._ref
    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)
