import json
from flask import Response
from StageHubAPI import db
from StageHubAPI.model import *
from sqlalchemy.orm import class_mapper

class JsonResponse(object):
    def __init__(self, message='', objects=[],
                status=200, mimetype='application/json'):
        self._message = message
        self._objects = objects
        self._mimetype = mimetype
        self._status = status

    @property
    def num_result(self):
        return len(self._objects)

    @property
    def objects(self):
        return self._objects

    @objects.setter
    def objects(self, value):
        self._objects = value

    @property
    def message(self):
        return self._message

    @message.setter
    def message(self, value):
        self._message = value

    @property
    def status(self):
        return self._status

    @status.setter
    def status(self, value):
        self._status = value

class ApiResponse(object):
    def __init__(self, message='', objects=[],
                 status=200, mimetype='application/json'):
        self._message = message
        self._objects = [self.object_to_dict(o) for o in objects]
        self._mimetype = mimetype
        self._status = status

    def object_to_dict(self, obj, found=None):
        if isinstance(obj, dict):
            return obj
        if found is None:
            found = set()
        mapper = class_mapper(obj.__class__)
        columns = [column.key for column in mapper.columns]

        def get_key_value(c): return (c, getattr(obj, c).isoformat()) \
            if isinstance(getattr(obj, c), db.DateTime) or isinstance(getattr(obj, c), datetime.datetime) \
            else (c, getattr(obj, c))

        out = dict(map(get_key_value, columns))
        for name, relation in mapper.relationships.items():
            if relation not in found:
                found.add(relation)
                related_obj = getattr(obj, name)
                if related_obj is not None:
                    if relation.uselist:
                        out[name] = [self.object_to_dict(
                            child, found) for child in related_obj]
                    else:
                        out[name] = self.object_to_dict(related_obj, found)
        return out

    @property
    def num_result(self):
        return len(self._objects)

    @property
    def objects(self):
        return self._objects

    @objects.setter
    def objects(self, value):
        self._objects = value

    @property
    def message(self):
        return self._message

    @message.setter
    def message(self, value):
        self._message = value

    @property
    def status(self):
        return self._status

    @status.setter
    def status(self, value):
        self._status = value

    def as_response(self, indent=0):
        return Response(response=self.as_json(indent=indent),
                        status=self._status,
                        mimetype=self._mimetype)

    def as_dict(self):
        return dict(num_result=self.num_result,
                    objects=self._objects,
                    message=self._message)

    def as_json(self, indent=0):
        return json.dumps(self.as_dict(), indent=indent)
