#!/usr/bin/env python
#
# Copyright (c) 2011-2013, Shopkick Inc.
# All rights reserved.
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# ---
# Author: John Egan <john@shopkick.com>

import pickle


class ApiObject(object):
    _api_attributes = []

    def __init__(self, *args, **kwargs):
        values = dict((k, None) for k, _ in self._api_attributes)
        values.update(zip([k for k, _ in self._api_attributes], args))
        values.update(kwargs)
        primitives = [int, str, bool, unicode, float, list, dict, set]
        values = dict((k, t(values[k]) if values[k] and t in primitives else values[k])
                      for k, t in self._api_attributes)
        self.__dict__.update(values)

    def dumps(self):
        return pickle.dumps(self, pickle.HIGHEST_PROTOCOL)

    @staticmethod
    def loads(strval):
        return pickle.loads(strval)

    def __hash__(self):
        return reduce(lambda x, y: x ^ hash(y), self.__dict__.iteritems(), 1)

    def __str__(self):
        return repr(self)

    def __repr__(self):
        return "%s(%s)" % (
            self.__class__.__name__,
            ", ".join("%s=%s" % (k, repr(v)) for k, v in self.__dict__.items())
        )

    def __eq__(self, other):
        return type(self) == type(other) and self.__dict__ == other.__dict__


class ErrorKey(ApiObject):
    _api_attributes = [
        ('filename', str),
        ('line_number', int),
        ('function_name', str),
        ('text', str),
    ]


class StackLine(ApiObject):
    _api_attributes = [
        ('filename', str),
        ('line_number', int),
        ('function_name', str),
        ('text', str),
        ('frame_locals', dict),
    ]


class RecordErrorRequest(ApiObject):
    _api_attributes = [
        ('traceback', list),
        ('exception_message', str),
        ('hostname', str),
        ('error_threshold', int),
        ('additional_info', str),
    ]


class ErrorInfo(ApiObject):
    _api_attributes = [
        ('error_count', int),
        ('developer_email', str),
        ('date', str),
        ('email_sent', bool),
        ('last_occurrence', str),
        ('is_known_error', bool),
        ('last_error_data', RecordErrorRequest),
    ]
