"""models.py - This file contains the class definitions for the Datastore
entities used by the Game. Because these classes are also regular Python
classes they can include methods (such as 'to_form' and 'new_game')."""

import random
from datetime import date
from protorpc import messages
#import google datastore
from google.appengine.ext import ndb

class User(ndb.Model):
    """User profile"""
    name = ndb.StringProperty(required=True)
    email =ndb.StringProperty()
    wins = ndb.IntegerProperty(default=0)
    total_played = ndb.IntegerProperty(default=0)
    win_ratio  = ndb.FloatProperty()

    @property
    def win_ratio(self):
        """calculates win ratio"""
        if self.total_played >0:
            return float(self.wins)/float(self.total_played)
        else:
            return 0
         
    def to_form(self):
        """ Returns a form representation of the user rankings """
        return UserRankingForm(name=self.name,
                               wins=self.wins,
                               total_played=self.total_played,
                               win_ratio= self.win_ratio)

    def record_win(self):
        """increments the total number of games played and wins and saves this info"""
        self.total_played = self.total_played + 1
        self.wins = self.wins + 1
        self.put()

    def record_loss(self):
        """ increments the total number of games of played and saves this info"""
        self.total_played = self.total_played + 1
        self.put()
 
class Game(ndb.Model):
    """Game object"""
    ai_move = ndb.StringProperty(required=True, default="")
    rounds_allowed = ndb.IntegerProperty(required=True)
    rounds_remaining = ndb.IntegerProperty(required=True, default=5)
    game_over = ndb.BooleanProperty(required=True, default=False)
    user = ndb.KeyProperty(required=True, kind='User')
    points = ndb.IntegerProperty(required=True)
    history = ndb.PickleProperty(required=True, default=[])

    @classmethod
    def new_game(cls, user, rounds):
        """Creates and returns a new game"""

        game = Game(user=user,
                    ai_move="",
                    rounds_allowed=rounds,
                    rounds_remaining=rounds,
                    history = [],
                    points=0,
                    game_over=False)
        game.put()
        return game

    def to_form(self, message):
        """Returns a GameForm representation of the Game"""
        form = GameForm()
        form.urlsafe_key = self.key.urlsafe()
        form.user_name = self.user.get().name
        form.rounds_remaining = self.rounds_remaining
        form.game_over = self.game_over
        form.ai_move = self.ai_move
        form.points = self.points
        form.message = message
        return form

    def end_game(self, won=False):
        """Ends the game - if won is True, the player won. - if won is False,
        the player lost."""
        self.game_over = True
        self.put()
        # Add the game to the score 'board'
        score = Score(user=self.user, date=date.today(), won=won, game_score = self.points)
        score.put()
        if won == True:
            self.user.get().record_win()
        elif won == False:
            self.user.get().record_loss()

class Score(ndb.Model):
    """Score object"""
    user = ndb.KeyProperty(required=True, kind='User')
    date = ndb.DateProperty(required=True)
    won = ndb.BooleanProperty(required=True)
    game_score = ndb.IntegerProperty(required=True)

    def to_form(self):
        return ScoreForm(user_name=self.user.get().name, won=self.won,
                         date=str(self.date), game_score=self.game_score)


class GameForm(messages.Message):
    """GameForm for outbound game state information"""
    urlsafe_key = messages.StringField(1, required=True)
    rounds_remaining = messages.IntegerField(2, required=True)
    game_over = messages.BooleanField(3, required=True)
    message = messages.StringField(4, required=True)
    ai_move = messages.StringField(5, required=True)
    user_name = messages.StringField(6, required=True)
    points = messages.IntegerField(7, default=0)

class GameForms(messages.Message):
    """Return multiple GameForms"""
    items = messages.MessageField(GameForm, 1, repeated=True)

class UserRankingForm(messages.Message):
    """User Ranking Form"""
    name = messages.StringField(1, required=True)
    wins = messages.IntegerField(2, required=True)
    total_played = messages.IntegerField(3, required=True)
    win_ratio = messages.FloatField(4, required=True)

class UserRankingForms(messages.Message):
    """Return multiple User Forms """
    items = messages.MessageField(UserRankingForm, 1, repeated=True)

class NewGameForm(messages.Message):
    """Used to create a new game"""
    user_name = messages.StringField(1, required=True)
    rounds = messages.IntegerField(2, default=5)

class MakeMoveForm(messages.Message):
    """Used to make a move in an existing game"""
    play = messages.StringField(1, required=True)

class ScoreForm(messages.Message):
    """ScoreForm for outbound Score information"""
    user_name = messages.StringField(1, required=True)
    date = messages.StringField(2, required=True)
    won = messages.BooleanField(3, required=True)
    game_score = messages.IntegerField(4)

class ScoreForms(messages.Message):
    """Return multiple ScoreForms"""
    items = messages.MessageField(ScoreForm, 1, repeated=True)

class StringMessage(messages.Message):
    """StringMessage"""
    message = messages.StringField(1, required=True)
