# -*- coding: utf-8 -*-

from google.appengine.ext import db
from google.appengine.api import images
import random
import string
from django1fields import email_re

#DB Models
class Member(db.Model):
    name = db.StringProperty()
    password = db.StringProperty()
    email = db.StringProperty()
    timeadded = db.DateTimeProperty(auto_now_add=True)

class LoginRecord(db.Model):
    code = db.StringProperty()
    member = db.ReferenceProperty(Member)
    timeadded = db.DateTimeProperty(auto_now_add=True)
    browser = db.StringProperty()
    ip = db.StringProperty()

class Photo(db.Model):
    member = db.ReferenceProperty(Member)
    filename = db.StringProperty()
    content = db.BlobProperty()
    thumb = db.BlobProperty()
    timeadded = db.DateTimeProperty(auto_now_add=True)

#End of DB Models

#This class will hold the functionality of the project
class AdrianRemembersMe():
    #Define error messages
    ERROR_OK, ERROR_USERNAME_NONE, ERROR_USERNAME_TAKEN, ERROR_PASSWORD_WEAK, ERROR_EMAIL_USED, ERROR_EMAIL_BAD, ERROR_LOGIN_BAD = range(0,7)
    
    #Define Defaults
    minimum_password_length = 3
    
    def logincookievalgenerate(self, membername):
        return membername+" "+(''.join([random.choice(string.letters + string.digits) for x in xrange(50)]))
    
    def logincookieclear(self, cookieval):
        q = db.GqlQuery("SELECT * FROM LoginRecord WHERE code = :1", cookieval)
        logins = q.fetch(10) # todo revisit this 10 later
        for login in logins:
            login.delete()

    def loginclearmember(self, member, cookieval):
        loginrecords = db.GqlQuery("SELECT * FROM LoginRecord WHERE member = :1", member)
        for loginrecord in loginrecords:
            if loginrecord.code != cookieval:
                loginrecord.delete()

        
    def logingetlist(self, amount):
        return db.GqlQuery("SELECT * FROM LoginRecord").fetch(amount) # todo revisit this 50 later
    
    def memberlogin(self, membername, password):
        member = db.GqlQuery("SELECT * FROM Member WHERE name = :1 LIMIT 1", membername).get()
        if member:
            if password == member.password:
                # ok, set cookie
                cookieval = self.logincookievalgenerate(member.name)
            
                # store in db
                loginrec = LoginRecord()
                loginrec.code = cookieval
                loginrec.member = member
                loginrec.put()
                
                return cookieval

            else:
                return None
                # todo processing for security
        
        return None

    def logincookievalmembernameget(self, cookieval):
        return cookieval.split(" ",1)[0]

    def membergetloggedin(self, cookieval):
        # check if login
        logins = db.GqlQuery("SELECT * FROM LoginRecord WHERE code = :1", cookieval)
        if logins.count():
            #What are we using this for?
            login = logins.fetch(1)
            #split off member name part
            
            #Couldn't we just split and looking up (member,randomval) in LoginRecord and using references to get associated member?
            #Why do we store member in LoginRecord for anyway?
            
            membername = self.logincookievalmembernameget(cookieval)
            
            # look up member and return member if found
            result = db.GqlQuery("SELECT * FROM Member WHERE name = :1 LIMIT 1", membername)
            if result.count():
                return result.get()
            
        return None
    
    def membercreate(self, membername, password, email, photofile = None, photoname = None):
        if (membername):
            mem = db.GqlQuery("SELECT * FROM Member WHERE name = :1 LIMIT 1", membername)
            if mem.count():
                return self.ERROR_USERNAME_TAKEN
            else:
                if len(password) >= self.minimum_password_length:
                    # todo improve email checking algorithm
                    if email_re.match(email):
                        # check if email has been used already
                        # eventually set it up so users can have multiple email addresses (or abstract out email part)
                        mem = db.GqlQuery("SELECT * FROM Member WHERE email = :1 LIMIT 1", email)
                        if mem.count():
                            return self.ERROR_EMAIL_USED
                        else:
                            member = Member()
                            member.name = membername
                            member.password = password
                            member.email = email
                            member.put()
                            
                            if photofile != None:
                                photo = Photo()
                                photo.member = member
                                photo.filename = photoname
                                photo.content = photofile
                                photo.thumb = images.resize(photo.content, 32, 32)
                                photo.put()
                            
                            return self.ERROR_OK
                    else:
                        return self.ERROR_EMAIL_BAD
                else:
                    return self.ERROR_PASSWORD_WEAK
        else:
            return self.ERROR_USERNAME_NONE
        
    def memberchangepassword(self, member, newpassword):
        # update pwd
        member.password = newpassword
        member.put()
 
        return self.ERROR_OK

    def memberget(self, membername):
        return db.GqlQuery("SELECT * FROM Member WHERE name = :1 LIMIT 1", membername).get()
    
    def membergetlist(self):
        return db.GqlQuery("SELECT * FROM Member")
    
    def emailisavailable(self, email):
        mem = db.GqlQuery("SELECT * FROM Member WHERE email = :1 LIMIT 1", email).get()
        
        return mem == None
