import json

import werkzeug.security
from google.appengine.ext import ndb
from google.appengine.datastore.datastore_query import Cursor
from datetime import datetime, timedelta

default_topography = {'water': [], 'mountain': []}

class User(ndb.Model):

    created = ndb.DateTimeProperty(auto_now_add=True)
    updated = ndb.DateTimeProperty(auto_now=True)
    username = ndb.StringProperty()
    name = ndb.StringProperty()
    last_name = ndb.StringProperty()
    email = ndb.StringProperty()
    password = ndb.StringProperty()
    activated = ndb.BooleanProperty(default=False)
    is_admin = ndb.BooleanProperty(default=False)

    def set_password(self, password):
        self.password = werkzeug.security.generate_password_hash(password)

    def check_password(self, password):
        return werkzeug.security.check_password_hash(self.password, password)

    @classmethod
    def get_by_email_or_username(cls, userinfo):
        #return cls.query(ndb.AND(cls.email == userinfo), ndb.OR(cls.username == userinfo), ndb.AND(cls.activated == True)).get()
        return cls.query(ndb.OR(cls.username == userinfo, cls.email == userinfo), cls.activated == True).get()

    def to_dict(cls):
	return {'created': cls.created,
			'updated': cls.updated,
            'key': cls.key.urlsafe(),
			'username': cls.username,
			'name': cls.name,
			'last_name': cls.last_name,
			'email': cls.email,
			'password': cls.password,
			'activated': cls.activated,
			'is_admin': cls.is_admin}

class Post(ndb.Model):
    created = ndb.DateTimeProperty(auto_now_add=True)
    updated = ndb.DateTimeProperty(auto_now=True)
    user = ndb.KeyProperty(kind=User)
    title = ndb.StringProperty()
    post = ndb.TextProperty()
    type = ndb.StringProperty(default='plain')

    @classmethod
    def fetch_by_user(cls, userkey):
	return cls.query(cls.user == ndb.Key(urlsafe = userkey)).fetch()

    @classmethod
    def fetch_page(cls, page_size, curs):
	#cursor = Cursor(urlsafe = curs)
        cursor = curs
	posts, next_cursor, more = cls.query().order(-cls.updated).fetch_page(page_size, start_cursor=cursor)
        for post in posts:
            post.userdata = User.query(User.key == post.user).get()
            post.updated_short = str(post.updated).split('.')[0]
	return posts, next_cursor, more

    @classmethod
    def get_post(cls, postkey):
        return cls.query(cls.key == ndb.Key(urlsafe = postkey)).get()

    @classmethod
    def fetch_all_posts(cls):
        return cls.query().order(-cls.updated).fetch()

class Config(ndb.Model):
    created = ndb.DateTimeProperty(auto_now_add=True)
    updated = ndb.DateTimeProperty(auto_now=True)
    name = ndb.StringProperty()
    value = ndb.JsonProperty()

    @classmethod
    def get_by_name(cls, name):
        return cls.query(cls.name == name).get()

class Monster(ndb.Model):
    owner = ndb.KeyProperty(kind=User)
    name = ndb.StringProperty()
    species = ndb.IntegerProperty(default=0)
    created = ndb.DateTimeProperty(auto_now_add=True)
    updated = ndb.DateTimeProperty(auto_now=True)

    @classmethod
    def fetch_by_owner(cls, userkey):
        return cls.query(cls.owner == userkey).fetch()

    @classmethod
    def fetch_by_owner_safe(cls, userkey):
        return cls.query(cls.owner == ndb.Key(urlsafe = userkey)).fetch()

    @classmethod
    def get_by_user_name(cls, userkey, name):
        monsters = cls.fetch_by_userkey(userkey)
        for monster in monsters:
            if monster.name == name:
                return monster

    @classmethod
    def get_by_urlkey(cls, urlkey):
        return cls.query(Monster.key == ndb.Key(urlsafe = urlkey)).get()

    def to_dict(cls):
        return {
            'key': cls.key.urlsafe(),
            'owner': cls.owner.urlsafe(),
            'name': cls.name,
            'species': cls.species,
            'created': cls.created,
            'updated': cls.updated,
        }

class Board(ndb.Model):
    x = ndb.IntegerProperty(default=250)
    y = ndb.IntegerProperty(default=150)
    topography = ndb.JsonProperty(default=default_topography)
    created = ndb.DateTimeProperty(auto_now_add=True)
    updated = ndb.DateTimeProperty(auto_now=True)

    @classmethod
    def get_by_key(cls, key):
        return cls.query(Board.key == key).get()

    @classmethod
    def get_by_urlkey(cls, key):
        return cls.query(Board.key == ndb.Key(urlsafe = key)).get()

    def to_dict(cls):
        return {
            'key': cls.key.urlsafe(),