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

"""\
© Copyright. All rights reserved.

"""

from __future__ import unicode_literals
import abc
import json
import logging
import logging.config
import six

LOG = logging.getLogger(__name__)


@six.add_metaclass(abc.ABCMeta)
class LogData(object):
    FIELDS = ()
    RAW_FIELDS = ()

    def __init__(self, record=None):
        self.data = dict()
        self.freefields = False if not hasattr(self, 'freefields') else self.freefields
        self.record = None
        if isinstance(record, logging.LogRecord):
            self.load(record)

    def get(self, field=None):
        if field is None:  # pylint: disable=no-else-return
            # Return 'data' dict
            return self.data
        elif field in self.data:
            # Return particular field from 'data' dict
            return self.data[field]
        else:
            return None

    def getDict(self):
        datadict = {}
        for key, val in self.get().items():
            if isinstance(val, LogData):
                datadict[key] = val.getDict()
            else:
                datadict[key] = val

        return datadict

    def getJSON(self):
        return json.dumps(self.getDict())

    def parseVal(self, field, value):
        if isinstance(value, dict):  # pylint: disable=no-else-return
            for k, v in value.items():
                value[k] = self.parseVal(k, v)
            return value
        # process_time needs to be a float for Kibana analysis
        elif field in self.RAW_FIELDS \
                or value is None \
                or field == "process_time" \
                or isinstance(value, (LogData, bool)):
            return value
        else:
            # If we haven't specified otherwise, make sure value is a string,
            # for consistency of data type and to make readable in logs/ES/Kibana
            return six.text_type(value)

    def set(self, field, value):
        if field in self.FIELDS or self.freefields:
            self.data[field] = self.parseVal(field, value)
        else:
            raise ValueError("No such field '" + field + "'")

        return self

    def load(self, record):
        self.record = record
        # Child should implement any class-specific loading code
        return
