# Copyright 2017-present Open Networking Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from mock import Mock
import random

def mock_enumerator(items):
    e = lambda:None
    e.all = lambda:items
    return e

# A list of all mock object stores that have been created
AllMockObjectStores = []

class MockObjectList:
    item_list = None

    def __init__(self, initial=None):
        self.id_counter = 0
        if initial:
            self.item_list=initial
        elif self.item_list is None:
            self.item_list=[]

    def get_items(self):
        return self.item_list

    def count(self):
        return len(self.get_items())

    def first(self):
        return self.get_items()[0]

    def all(self):
        return self.get_items()

    def filter(self, **kwargs):
        items = self.get_items()
        for (k,v) in kwargs.items():
            items = [x for x in items if getattr(x,k) == v]
        return items

    def get(self, **kwargs):
        objs = self.filter(**kwargs)
        if not objs:
            raise Exception("No objects matching %s" % str(kwargs))
        return objs[0]

class MockObjectStore(MockObjectList):
    def save(self, o):
        if (not hasattr(o,"id")) or (not o.id) or (o.id==98052):
            for item in self.get_items():
                if item.id >= self.id_counter:
                    self.id_counter = item.id + 1

            o.id = self.id_counter
            self.id_counter = self.id_counter + 1

        for item in self.get_items():
            if item.id == o.id:
                item = o
                break
        else:
            self.get_items().append(o)

class MockObject:
    objects = None
    id = None
    deleted = False

    def __init__(self, **kwargs):
        setattr(self, 'backend_code', 0)
        setattr(self, 'id', 98052)
        setattr(self, 'pk', random.randint(0, 1<<30))
        
        for (k,v) in kwargs.items():
            setattr(self,k,v)

    @property
    def self_content_type_id(self):
        return self.__class__.__name__

    @property
    def leaf_model(self):
        return self

    def save(self, update_fields=[], always_update_timestamp=False):
        if self.objects:
            self.objects.save(self)

    def delete(self):
        pass

    def tologdict(self):
        return {}

def get_MockObjectStore(x):
    store = globals()["Mock%sObjects" % x]()
    if not store in AllMockObjectStores:
        AllMockObjectStores.append(store)
    return store

class ModelAccessor:
    def check_db_connection_ok(self):
        return True

    def fetch_pending(self, model, deleted = False):
        num = random.randint(1, 5)
        object_list = []

        for i in range(num):
            if isinstance(model, list):
                model = model[0]

            try:
                obj = model()
            except:
                import pdb
                pdb.set_trace()

            obj.name = "Opinionated Berry %d"%i
            object_list.append(obj)
        
        return object_list

    def reset_all_object_stores(self):
        for store in AllMockObjectStores:
            store.items = []

    def get_model_class(self, classname):
        return globals()[classname]

model_accessor = ModelAccessor()

class ObjectSet(object):
    def __init__(self, objects):
        self.objects = objects

    def all(self):
        return self.objects
    
#####
# DO NOT MODIFY THE CLASSES BELOW. THEY ARE AUTOGENERATED.
# 

{% for m in proto.messages -%}
class Mock{{ m.name }}Objects(MockObjectStore): pass
class {{ m.name }}(MockObject):
    objects = get_MockObjectStore("{{ m.name }}")
    {% for f in xproto_base_fields(m, proto.message_table) +  m.fields -%}
    {{ f.name }} = {{ xproto_first_non_empty([f.options.default, "None"]) }}
    {% if f.link -%}{{ f.name }}_id = None{% endif %}
    {% endfor %}
    leaf_model_name = "{{ m.name }}"
{% endfor %}
