#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from poppy.core.generic.metaclasses import Singleton
from poppy.core.logger import logger

__all__ = ['CDFToFill', 'fill_records', 'fill_dict']


def fill_records(records):
    _filler(records, records.dtype.names)


def fill_dict(records):
    _filler(records, records.keys())


def _filler(records, names):
    # the converter
    converter = CDFToFill()

    # loop over fields
    for name in names:
        # dtype of the record
        dtype = records[name].dtype.name

        # the to fill with
        value = converter(dtype)
        logger.debug(
            'Fill {0} record with {1} for type {2}'.format(name, value, dtype,)
        )

        # fill with value
        records[name].fill(value)


class CDFToFill(object, metaclass=Singleton):
    """
    To create a mapping between the CDF units and their fill values.
    """

    def __init__(self):
        self.mapping = {
            'CDF_BYTE': -128,
            'CDF_INT1': -128,
            'int8': -128,
            'CDF_UINT1': 255,
            'uint8': 255,
            'CDF_INT2': -32768,
            'int16': -32768,
            'CDF_UINT2': 65535,
            'uint16': 65535,
            'CDF_INT4': -2147483648,
            'int32': -2147483648,
            'CDF_UINT4': 4294967295,
            'uint32': 4294967295,
            'CDF_INT8': -9223372036854775808,
            'int64': -9223372036854775808,
            'uint64': 18446744073709551615,
            'float': -1e31,
            'float16': -1e31,
            'CDF_REAL4': -1e31,
            'CDF_FLOAT': -1e31,
            'float32': -1e31,
            'CDF_REAL8': -1e31,
            'CDF_DOUBLE': -1e31,
            'float64': -1e31,
            'CDF_EPOCH': 0.0,
            'CDF_TIME_TT2000': -9223372036854775808,
            'CDF_CHAR': ' ',
            'CDF_UCHAR': ' ',
        }

        self.validmin_mapping = {
            'CDF_BYTE': -127,
            'CDF_INT1': -127,
            'CDF_UINT1': 0,
            'CDF_INT2': -32767,
            'CDF_UINT2': 0,
            'CDF_INT4': -2147483647,
            'CDF_UINT4': 0,
            'CDF_INT8': -9223372036854775807,
            'CDF_REAL4': -1e30,
            'CDF_FLOAT': -1e30,
            'CDF_REAL8': -1e30,
            'CDF_DOUBLE': -1e30,
            'CDF_TIME_TT2000': -9223372036854775807,
        }

        self.validmax_mapping = {
            'CDF_BYTE': 127,
            'CDF_INT1': 127,
            'CDF_UINT1': 254,
            'CDF_INT2': 32767,
            'CDF_UINT2': 65534,
            'CDF_INT4': 2147483647,
            'CDF_UINT4': 4294967294,
            'CDF_INT8': 9223372036854775807,
            'CDF_REAL4': 3.4028235e38,
            'CDF_FLOAT': 3.4028235e38,
            'CDF_REAL8': 1.7976931348623157e308,
            'CDF_DOUBLE': 1.7976931348623157e308,
            'CDF_TIME_TT2000': 9223372036854775807,
        }

    def __call__(self, value):
        if value not in self.mapping:
            logger.error('{0} fill type not mapped'.format(value))
            return
        return self.mapping[value]

    def validmin(self, value):
        if value not in self.validmin_mapping:
            logger.error('{0} validmin type not mapped'.format(value))
            return
        return self.validmin_mapping[value]

    def validmax(self, value):
        if value not in self.validmax_mapping:
            logger.error('{0} validmax type not mapped'.format(value))
            return
        return self.validmax_mapping[value]


# vim: set tw=79 :
