import json
import os
import time
from datetime import datetime
from pandac.PandaModules import *
from direct.distributed.MsgTypes import *
from direct.gui.DirectGui import *
from direct.fsm import StateData
from direct.fsm import ClassicFSM
from direct.fsm import State
from direct.directnotify import DirectNotifyGlobal
from direct.task import Task
from otp.otpgui import OTPDialog
from otp.otpbase import OTPLocalizer
from otp.otpbase import OTPGlobals
from otp.uberdog.AccountDetailRecord import AccountDetailRecord, SubDetailRecord
import TTAccount
import GuiScreen

class LoginScreen(StateData.StateData, GuiScreen.GuiScreen):
    AutoLoginName = base.config.GetString('%s-auto-login%s' % (game.name, os.getenv('otp_client', '')), '')
    AutoLoginPassword = base.config.GetString('%s-auto-password%s' % (game.name, os.getenv('otp_client', '')), '')
    notify = DirectNotifyGlobal.directNotify.newCategory('LoginScreen')
    ActiveEntryColor = Vec4(1, 1, 1, 1)
    InactiveEntryColor = Vec4(0.8, 0.8, 0.8, 1)

    def __init__(self, cr, doneEvent):
        self.notify.debug('__init__')
        StateData.StateData.__init__(self, doneEvent)
        GuiScreen.GuiScreen.__init__(self)
        self.cr = cr
        self.loginInterface = self.cr.loginInterface
        self.userName = ''
        self.password = ''
        self.fsm = ClassicFSM.ClassicFSM('LoginScreen', [State.State('off', self.enterOff, self.exitOff, ['login', 'waitForLoginResponse']),
         State.State('login', self.enterLogin, self.exitLogin, ['waitForLoginResponse', 'login', 'showLoginFailDialog']),
         State.State('showLoginFailDialog', self.enterShowLoginFailDialog, self.exitShowLoginFailDialog, ['login', 'showLoginFailDialog']),
         State.State('waitForLoginResponse', self.enterWaitForLoginResponse, self.exitWaitForLoginResponse, ['login', 'showLoginFailDialog', 'showConnectionProblemDialog']),
         State.State('showConnectionProblemDialog', self.enterShowConnectionProblemDialog, self.exitShowConnectionProblemDialog, ['login'])], 'off', 'off')
        self.fsm.enterInitialState()

    def load(self):
        self.notify.debug('load')
        masterScale = 0.8
        textScale = 0.1 * masterScale
        entryScale = 0.08 * masterScale
        lineHeight = 0.21 * masterScale
        buttonScale = 1.15 * masterScale
        buttonLineHeight = 0.14 * masterScale
        self.frame = DirectFrame(parent=aspect2d, relief=None, sortOrder=20)
        self.frame.hide()
        linePos = -0.26
        self.nameLabel = DirectLabel(parent=self.frame, relief=None, pos=(-0.21, 0, linePos), text=OTPLocalizer.LoginScreenUserName, text_scale=textScale, text_align=TextNode.ARight)
        self.nameEntry = DirectEntry(parent=self.frame, relief=DGG.SUNKEN, borderWidth=(0.1, 0.1), scale=entryScale, pos=(-0.125, 0.0, linePos), width=OTPGlobals.maxLoginWidth, numLines=1, focus=0, cursorKeys=1)
        linePos -= lineHeight
        self.passwordLabel = DirectLabel(parent=self.frame, relief=None, pos=(-0.21, 0, linePos), text=OTPLocalizer.LoginScreenPassword, text_scale=textScale, text_align=TextNode.ARight)
        self.passwordEntry = DirectEntry(parent=self.frame, relief=DGG.SUNKEN, borderWidth=(0.1, 0.1), scale=entryScale, pos=(-0.125, 0.0, linePos), width=OTPGlobals.maxLoginWidth, numLines=1, focus=0, cursorKeys=1, obscured=1, command=self.__handleLoginPassword)
        linePos -= lineHeight
        buttonImageScale = (1.7, 1.1, 1.1)
        self.loginButton = DirectButton(parent=self.frame, relief=DGG.RAISED, borderWidth=(0.01, 0.01), pos=(0, 0, linePos), scale=buttonScale, text=OTPLocalizer.LoginScreenLogin, text_scale=0.06, text_pos=(0, -0.02), command=self.__handleLoginButton)
        linePos -= buttonLineHeight
        self.createAccountButton = DirectButton(parent=self.frame, relief=DGG.RAISED, borderWidth=(0.01, 0.01), pos=(0, 0, linePos), scale=buttonScale, text=OTPLocalizer.LoginScreenCreateAccount, text_scale=0.06, text_pos=(0, -0.02), command=self.__handleCreateAccount)
        linePos -= buttonLineHeight
        self.quitButton = DirectButton(parent=self.frame, relief=DGG.RAISED, borderWidth=(0.01, 0.01), pos=(0, 0, linePos), scale=buttonScale, text=OTPLocalizer.LoginScreenQuit, text_scale=0.06, text_pos=(0, -0.02), command=self.__handleQuit)
        linePos -= buttonLineHeight
        self.dialogDoneEvent = 'loginDialogAck'
        dialogClass = OTPGlobals.getGlobalDialogClass()
        self.dialog = dialogClass(dialogName='loginDialog', doneEvent=self.dialogDoneEvent, message='', style=OTPDialog.Acknowledge, sortOrder=DGG.NO_FADE_SORT_INDEX + 100)
        self.dialog.hide()
        self.failDialog = DirectFrame(parent=aspect2dp, relief=DGG.RAISED, borderWidth=(0.01, 0.01), pos=(0, 0.1, 0), text='', text_scale=0.08, text_pos=(0.0, 0.3), text_wordwrap=15, sortOrder=DGG.NO_FADE_SORT_INDEX)
        linePos = -.05
        self.failTryAgainButton = DirectButton(parent=self.failDialog, relief=DGG.RAISED, borderWidth=(0.01, 0.01), pos=(0, 0, linePos), scale=0.9, text=OTPLocalizer.LoginScreenTryAgain, text_scale=0.06, text_pos=(0, -.02), command=self.__handleFailTryAgain)
        linePos -= buttonLineHeight
        self.failCreateAccountButton = DirectButton(parent=self.failDialog, relief=DGG.RAISED, borderWidth=(0.01, 0.01), pos=(0, 0, linePos), scale=0.9, text=OTPLocalizer.LoginScreenCreateAccount, text_scale=0.06, text_pos=(0, -.02), command=self.__handleFailCreateAccount)
        linePos -= buttonLineHeight
        self.failDialog.hide()
        self.connectionProblemDialogDoneEvent = 'loginConnectionProblemDlgAck'
        dialogClass = OTPGlobals.getGlobalDialogClass()
        self.connectionProblemDialog = dialogClass(dialogName='connectionProblemDialog', doneEvent=self.connectionProblemDialogDoneEvent, message='', style=OTPDialog.Acknowledge, sortOrder=DGG.NO_FADE_SORT_INDEX + 100)
        self.connectionProblemDialog.hide()
        return

    def unload(self):
        self.notify.debug('unload')
        self.nameEntry.destroy()
        self.passwordEntry.destroy()
        self.failTryAgainButton.destroy()
        self.failCreateAccountButton.destroy()
        self.createAccountButton.destroy()
        self.loginButton.destroy()
        self.quitButton.destroy()
        self.dialog.cleanup()
        del self.dialog
        self.failDialog.destroy()
        del self.failDialog
        self.connectionProblemDialog.cleanup()
        del self.connectionProblemDialog
        self.frame.destroy()
        del self.fsm
        del self.loginInterface
        del self.cr

    def enter(self):
        if self.cr.blue:
            self.userName = 'blue'
            self.password = self.cr.blue
            self.fsm.request('waitForLoginResponse')
        elif self.cr.playToken:
            self.userName = '*'
            self.password = self.cr.playToken
            self.fsm.request('waitForLoginResponse')
        elif hasattr(self.cr, 'DISLToken') and self.cr.DISLToken:
            self.userName = '*'
            self.password = self.cr.DISLToken
            self.fsm.request('waitForLoginResponse')
        elif self.AutoLoginName:
            self.userName = self.AutoLoginName
            self.password = self.AutoLoginPassword
            self.fsm.request('waitForLoginResponse')
        else:
            self.fsm.request('login')

    def exit(self):
        self.frame.hide()
        self.ignore(self.dialogDoneEvent)
        self.fsm.requestFinalState()

    def enterOff(self):
        pass

    def exitOff(self):
        pass

    def enterLogin(self):
        self.cr.resetPeriodTimer(None)
        self.userName = ''
        self.password = ''
        self.userName = launcher.getLastLogin()
        if self.userName and self.nameEntry.get():
            if self.userName != self.nameEntry.get():
                self.userName = ''
        self.frame.show()
        self.nameEntry.enterText(self.userName)
        self.passwordEntry.enterText(self.password)
        self.focusList = [self.nameEntry, self.passwordEntry]
        focusIndex = 0
        if self.userName:
            focusIndex = 1
        self.startFocusMgmt(startFocus=focusIndex)
        return

    def exitLogin(self):
        self.stopFocusMgmt()

    def enterShowLoginFailDialog(self, msg):
        base.transitions.fadeScreen(0.5)
        self.failDialog['text'] = msg
        self.failDialog.show()

    def __handleFailTryAgain(self):
        self.fsm.request('login')

    def __handleFailCreateAccount(self):
        messenger.send(self.doneEvent, [{'mode': 'createAccount'}])

    def __handleFailNoNewAccountsAck(self):
        self.dialog.hide()
        self.fsm.request('showLoginFailDialog', [self.failDialog['text']])

    def exitShowLoginFailDialog(self):
        base.transitions.noTransitions()
        self.failDialog.hide()

    def __handleLoginPassword(self, password):
        if password != '':
            if self.nameEntry.get() != '':
                self.__handleLoginButton()

    def __handleLoginButton(self):
        self.removeFocus()
        self.userName = self.nameEntry.get()
        self.password = self.passwordEntry.get()
        if self.userName == '':
            self.dialog.setMessage(OTPLocalizer.LoginScreenLoginPrompt)
            self.dialog.show()
            self.acceptOnce(self.dialogDoneEvent, self.__handleEnterLoginAck)
        else:
            self.fsm.request('waitForLoginResponse')

    def __handleQuit(self):
        self.removeFocus()
        messenger.send(self.doneEvent, [{'mode': 'quit'}])

    def __handleCreateAccount(self):
        self.removeFocus()
        messenger.send(self.doneEvent, [{'mode': 'createAccount'}])

    def enterWaitForLoginResponse(self):
        self.cr.handler = self.handleWaitForLoginResponse
        self.cr.userName = self.userName
        self.cr.password = self.password
        try:
            error = self.loginInterface.authorize(self.userName, self.password)
        except TTAccount.TTAccountException, e:
            self.fsm.request('showConnectionProblemDialog', [str(e)])
            return

        if error:
            self.notify.info(error)
            freeTimeExpired = self.loginInterface.getErrorCode() == 10
            if freeTimeExpired:
                self.cr.logAccountInfo()
                messenger.send(self.doneEvent, [{'mode': 'freeTimeExpired'}])
            else:
                self.fsm.request('showLoginFailDialog', [error])
        else:
            self.loginInterface.sendLoginMsg()
            self.waitForDatabaseTimeout(requestName='WaitForLoginResponse')

    def exitWaitForLoginResponse(self):
        self.cleanupWaitingForDatabase()
        self.cr.handler = None
        return

    def enterShowConnectionProblemDialog(self, msg):
        self.connectionProblemDialog.setMessage(msg)
        self.connectionProblemDialog.show()
        self.acceptOnce(self.connectionProblemDialogDoneEvent, self.__handleConnectionProblemAck)

    def __handleConnectionProblemAck(self):
        self.connectionProblemDialog.hide()
        self.fsm.request('login')

    def exitShowConnectionProblemDialog(self):
        pass

    if not config.GetBool('astron-support', True):
        def handleWaitForLoginResponse(self, msgType, di):
            if msgType == CLIENT_LOGIN_2_RESP:
                self.handleLoginResponseMsg2(di)
            elif msgType == CLIENT_LOGIN_RESP:
                self.handleLoginResponseMsg(di)
            elif msgType == CLIENT_LOGIN_3_RESP:
                self.handleLoginResponseMsg3(di)
            elif msgType == CLIENT_LOGIN_TOONTOWN_RESP:
                self.handleLoginToontownResponse(di)
            else:
                self.cr.handleMessageType(msgType, di)
    else:
        def handleWaitForLoginResponse(self, msgType, di):
            if msgType == CLIENT_HELLO_RESP:
                self.handleHelloResp()
            else:
                self.cr.handleMessageType(msgType, di)

        def handleHelloResp(self):
            self.cr.startHeartbeat()
            self.cr.astronLoginManager.handleRequestLogin()

    def getExtendedErrorMsg(self, errorString):
        prefix = 'Bad DC Version Compare'
        if len(errorString) < len(prefix):
            return errorString
        if errorString[:len(prefix)] == prefix:
            return '%s%s' % (errorString, ', address=%s' % base.cr.getServerAddress())
        return errorString

    def handleLoginResponseMsg3(self, di):
        now = time.time()
        returnCode = di.getInt8()
        errorString = self.getExtendedErrorMsg(di.getString())
        self.notify.info('Login response return code %s' % returnCode)
        if returnCode != 0:
            self.notify.info('Login failed: %s' % errorString)
            messenger.send(self.doneEvent, [{'mode': 'reject'}])
            return
        accountDetailRecord = AccountDetailRecord()
        accountDetailRecord.openChatEnabled = di.getString() == 'YES'
        accountDetailRecord.createFriendsWithChat = di.getString() == 'YES'
        chatCodeCreation = di.getString()
        accountDetailRecord.chatCodeCreation = chatCodeCreation == 'YES'
        parentControlledChat = chatCodeCreation == 'PARENT'
        access = di.getString()
        if access == 'VELVET':
            access = OTPGlobals.AccessVelvetRope
        elif access == 'FULL':
            access = OTPGlobals.AccessFull
        else:
            self.notify.warning('Unknown access: %s' % access)
            access = OTPGlobals.AccessUnknown
        accountDetailRecord.piratesAccess = access
        accountDetailRecord.familyAccountId = di.getInt32()
        accountDetailRecord.playerAccountId = di.getInt32()
        accountDetailRecord.playerName = di.getString()
        accountDetailRecord.playerNameApproved = di.getInt8()
        accountDetailRecord.maxAvatars = di.getInt32()
        self.cr.openChatAllowed = accountDetailRecord.openChatEnabled
        self.cr.secretChatAllowed = accountDetailRecord.chatCodeCreation or parentControlledChat
        self.cr.setIsPaid(accountDetailRecord.piratesAccess)
        self.userName = accountDetailRecord.playerName
        self.cr.userName = accountDetailRecord.playerName
        accountDetailRecord.numSubs = di.getUint16()
        for i in range(accountDetailRecord.numSubs):
            subDetailRecord = SubDetailRecord()
            subDetailRecord.subId = di.getUint32()
            subDetailRecord.subOwnerId = di.getUint32()
            subDetailRecord.subName = di.getString()
            subDetailRecord.subActive = di.getString()
            access = di.getString()
            if access == 'VELVET':
                access = OTPGlobals.AccessVelvetRope
            elif access == 'FULL':
                access = OTPGlobals.AccessFull
            else:
                access = OTPGlobals.AccessUnknown
            subDetailRecord.subAccess = access
            subDetailRecord.subLevel = di.getUint8()
            subDetailRecord.subNumAvatars = di.getUint8()
            subDetailRecord.subNumConcur = di.getUint8()
            subDetailRecord.subFounder = di.getString() == 'YES'
            accountDetailRecord.subDetails[subDetailRecord.subId] = subDetailRecord

        accountDetailRecord.WLChatEnabled = di.getString() == 'YES'
        if accountDetailRecord.WLChatEnabled:
            self.cr.whiteListChatEnabled = 1
        else:
            self.cr.whiteListChatEnabled = 0
        self.notify.info('End of DISL token parse')
        if base.logPrivateInfo:
            self.notify.info('accountDetailRecord: %s' % accountDetailRecord)
        self.cr.accountDetailRecord = accountDetailRecord
        self.__handleLoginSuccess()

    def handleLoginResponseMsg2(self, di):
        self.notify.debug('handleLoginResponseMsg2')
        if base.logPrivateInfo:
            if self.notify.getDebug():
                dgram = di.getDatagram()
                dgram.dumpHex(ostream)
        now = time.time()
        returnCode = di.getUint8()
        errorString = self.getExtendedErrorMsg(di.getString())
        self.userName = di.getString()
        self.cr.userName = self.userName
        accountDetailRecord = AccountDetailRecord()
        self.cr.accountDetailRecord = accountDetailRecord
        canChat = di.getUint8()
        self.cr.secretChatAllowed = canChat
        if base.logPrivateInfo:
            self.notify.info('Chat from game server login: %s' % canChat)
        sec = di.getUint32()
        usec = di.getUint32()
        serverTime = sec + usec / 1000000.0
        self.cr.serverTimeUponLogin = serverTime
        self.cr.clientTimeUponLogin = now
        self.cr.globalClockRealTimeUponLogin = globalClock.getRealTime()
        if hasattr(self.cr, 'toontownTimeManager'):
            self.cr.toontownTimeManager.updateLoginTimes(serverTime, now, self.cr.globalClockRealTimeUponLogin)
        serverDelta = serverTime - now
        self.cr.setServerDelta(serverDelta)
        self.notify.setServerDelta(serverDelta, 28800)
        self.isPaid = di.getUint8()
        self.cr.setIsPaid(self.isPaid)
        if self.isPaid:
            launcher.setPaidUserLoggedIn()
        if base.logPrivateInfo:
            self.notify.info('Paid from game server login: %s' % self.isPaid)
        self.cr.resetPeriodTimer(None)
        if di.getRemainingSize() >= 4:
            minutesRemaining = di.getInt32()
            if base.logPrivateInfo:
                self.notify.info('Minutes remaining from server %s' % minutesRemaining)
            if base.logPrivateInfo:
                if minutesRemaining >= 0:
                    self.notify.info('Spawning period timer')
                    self.cr.resetPeriodTimer(minutesRemaining * 60)
                elif self.isPaid:
                    self.notify.warning('Negative minutes remaining for paid user (?)')
                else:
                    self.notify.warning('Not paid, but also negative minutes remaining (?)')
        elif base.logPrivateInfo:
            self.notify.info('Minutes remaining not returned from server; not spawning period timer')
        familyStr = di.getString()
        WhiteListResponse = di.getString()
        if WhiteListResponse == 'YES':
            self.cr.whiteListChatEnabled = 1
        else:
            self.cr.whiteListChatEnabled = 0
        if di.getRemainingSize() > 0:
            self.cr.accountDays = self.parseAccountDays(di.getInt32())
        else:
            self.cr.accountDays = 100000
        if di.getRemainingSize() > 0:
            self.lastLoggedInStr = di.getString()
            self.notify.info('last logged in = %s' % self.lastLoggedInStr)
        else:
            self.lastLoggedInStr = ''
        self.cr.lastLoggedIn = datetime.now()
        if hasattr(self.cr, 'toontownTimeManager'):
            self.cr.lastLoggedIn = self.cr.toontownTimeManager.convertStrToToontownTime(self.lastLoggedInStr)
        self.cr.withParentAccount = False
        self.notify.info('Login response return code %s' % returnCode)
        if returnCode == 0:
            self.__handleLoginSuccess()
        elif returnCode == -13:
            self.notify.info('Period Time Expired')
            self.fsm.request('showLoginFailDialog', [OTPLocalizer.LoginScreenPeriodTimeExpired])
        else:
            self.notify.info('Login failed: %s' % errorString)
            messenger.send(self.doneEvent, [{'mode': 'reject'}])
        return

    def handleLoginResponseMsg(self, di):
        self.notify.debug('handleLoginResponseMsg1')
        if base.logPrivateInfo:
            if self.notify.getDebug():
                dgram = di.getDatagram()
                dgram.dumpHex(ostream)
        now = time.time()
        accountDetailRecord = AccountDetailRecord()
        self.cr.accountDetailRecord = accountDetailRecord
        returnCode = di.getUint8()
        accountCode = di.getUint32()
        errorString = self.getExtendedErrorMsg(di.getString())
        sec = di.getUint32()
        usec = di.getUint32()
        serverTime = sec + usec / 1000000.0
        serverDelta = serverTime - now
        self.cr.serverTimeUponLogin = serverTime
        self.cr.clientTimeUponLogin = now
        self.cr.globalClockRealTimeUponLogin = globalClock.getRealTime()
        if hasattr(self.cr, 'toontownTimeManager'):
            self.cr.toontownTimeManager.updateLoginTimes(serverTime, now, self.cr.globalClockRealTimeUponLogin)
        self.cr.setServerDelta(serverDelta)
        self.notify.setServerDelta(serverDelta, 28800)
        if di.getRemainingSize() > 0:
            self.cr.accountDays = self.parseAccountDays(di.getInt32())
        else:
            self.cr.accountDays = 100000
        if di.getRemainingSize() > 0:
            WhiteListResponse = di.getString()
        else:
            WhiteListResponse = 'NO'
        if WhiteListResponse == 'YES':
            self.cr.whiteListChatEnabled = 1
        else:
            self.cr.whiteListChatEnabled = 0
        self.lastLoggedInStr = base.config.GetString('last-logged-in', '')
        self.cr.lastLoggedIn = datetime.now()
        if hasattr(self.cr, 'toontownTimeManager'):
            self.cr.lastLoggedIn = self.cr.toontownTimeManager.convertStrToToontownTime(self.lastLoggedInStr)
        self.cr.withParentAccount = base.config.GetBool('dev-with-parent-account', 0)
        self.notify.info('Login response return code %s' % returnCode)
        if returnCode == 0:
            self.__handleLoginSuccess()
        elif returnCode == 12:
            self.notify.info('Bad password')
            self.fsm.request('showLoginFailDialog', [OTPLocalizer.LoginScreenBadPassword])
        elif returnCode == 14:
            self.notify.info('Bad word in user name')
            self.fsm.request('showLoginFailDialog', [OTPLocalizer.LoginScreenInvalidUserName])
        elif returnCode == 129:
            self.notify.info('Username not found')
            self.fsm.request('showLoginFailDialog', [OTPLocalizer.LoginScreenUserNameNotFound])
        else:
            self.notify.info('Login failed: %s' % errorString)
            messenger.send(self.doneEvent, [{'mode': 'reject'}])

    def __handleLoginSuccess(self):
        self.cr.logAccountInfo()
        launcher.setGoUserName(self.userName)
        launcher.setLastLogin(self.userName)
        launcher.setUserLoggedIn()
        if self.loginInterface.freeTimeExpires == -1:
            launcher.setPaidUserLoggedIn()
        if self.loginInterface.needToSetParentPassword():
            messenger.send(self.doneEvent, [{'mode': 'getChatPassword'}])
        else:
            messenger.send(self.doneEvent, [{'mode': 'success'}])

    def __handleEnterLoginAck(self):
        self.dialog.hide()
        self.fsm.request('login')

    def __handleNoNewAccountsAck(self):
        self.dialog.hide()
        self.fsm.request('login')

    def parseAccountDays(self, accountDays):
        result = 100000
        if accountDays >= 0:
            result = accountDays
        else:
            self.notify.warning('account days is negative %s' % accountDays)
        self.notify.debug('result=%s' % result)
        return result

    if not config.GetBool('astron-support', True):
        def handleLoginToontownResponse(self, di):
            self.notify.debug("handleLoginToontownResponse")
            if 1:
                if base.logPrivateInfo:
                    dgram = di.getDatagram()
                    dgram.dumpHex(ostream)
            now = time.time()
            returnCode = di.getUint8()
            respString = di.getString()
            errorString = self.getExtendedErrorMsg(respString)
            self.accountNumber = di.getUint32()
            self.cr.DISLIdFromLogin = self.accountNumber
            self.accountName = di.getString()
            self.accountNameApproved = di.getUint8()
            accountDetailRecord = AccountDetailRecord()
            self.cr.accountDetailRecord = accountDetailRecord
            self.openChatEnabled = di.getString() == "YES"
            createFriendsWithChat = di.getString()
            canChat = createFriendsWithChat == "YES" or createFriendsWithChat == "CODE"
            self.cr.secretChatAllowed = canChat
            if base.logPrivateInfo:
                self.notify.info("CREATE_FRIENDS_WITH_CHAT from game server login: %s %s" % (createFriendsWithChat, canChat))
            self.chatCodeCreationRule = di.getString()
            self.cr.chatChatCodeCreationRule = self.chatCodeCreationRule
            if base.logPrivateInfo:
                self.notify.info("Chat code creation rule = %s" % self.chatCodeCreationRule)
            self.cr.secretChatNeedsParentPassword = self.chatCodeCreationRule == "PARENT"
            sec = di.getUint32()
            usec = di.getUint32()
            serverTime = sec + (usec/1000000.0)
            self.cr.serverTimeUponLogin = serverTime
            self.cr.clientTimeUponLogin = now
            self.cr.globalClockRealTimeUponLogin = globalClock.getRealTime()
            if hasattr(self.cr, "toontownTimeManager"):
                self.cr.toontownTimeManager.updateLoginTimes(serverTime, now, self.cr.globalClockRealTimeUponLogin)
            serverDelta = serverTime - now
            self.cr.setServerDelta(serverDelta)
            self.notify.setServerDelta(serverDelta, 28800)
            access = di.getString()
            self.isPaid = access == "FULL"
            self.cr.parentPasswordSet = self.isPaid
            self.cr.setIsPaid(self.isPaid)
            if self.isPaid:
                launcher.setPaidUserLoggedIn()
            if base.logPrivateInfo:
                self.notify.info("Paid from game server login: %s" % self.isPaid)
            WhiteListResponse = di.getString()
            if WhiteListResponse == "YES":
                self.cr.whiteListChatEnabled = 1
            else:
                self.cr.whiteListChatEnabled = 0
            self.lastLoggedInStr = di.getString()
            self.cr.lastLoggedIn = datetime.now()
            if hasattr(self.cr, "toontownTimeManager"):
                self.cr.lastLoggedIn = self.cr.toontownTimeManager.convertStrToToontownTime(self.lastLoggedInStr)
            if di.getRemainingSize() > 0:
                self.cr.accountDays = self.parseAccountDays(di.getInt32())
            else:
                self.cr.accountDays = 100000
            self.toonAccountType = di.getString()
            if self.toonAccountType == "WITH_PARENT_ACCOUNT":
                self.cr.withParentAccount = True
            elif self.toonAccountType == "NO_PARENT_ACCOUNT":
                self.cr.withParentAccount = False
            else:
                self.notify.error("unknown toon account type %s" % self.toonAccountType)
            if base.logPrivateInfo:
                self.notify.info("toonAccountType=%s" % self.toonAccountType)
            self.userName = di.getString()
            self.cr.userName = self.userName
            self.notify.info("Login response return code %s" % returnCode)
            if returnCode == 0:
                self.__handleLoginSuccess()
            elif returnCode == -13:
                self.notify.info("Period Time Expired")
                self.fsm.request("showLoginFailDialog", [OTPLocalizer.LoginScreenPeriodTimeExpired])
            else:
                self.notify.info("Login failed: %s" % errorString)
                messenger.send(self.doneEvent, [{'mode': 'reject'}])
    else:
        def handleLoginToontownResponse(self, responseBlob):
            self.notify.debug("handleLoginToontownResponse")
            responseData = json.loads(responseBlob)
            now = time.time()
            returnCode = responseData.get('returnCode')
            respString = responseData.get('respString')
            errorString = self.getExtendedErrorMsg(respString)
            self.accountNumber = responseData.get('accountNumber')
            self.cr.DISLIdFromLogin = self.accountNumber
            accountDetailRecord = AccountDetailRecord()
            self.cr.accountDetailRecord = accountDetailRecord
            createFriendsWithChat = responseData.get('createFriendsWithChat')
            canChat = createFriendsWithChat == "YES" or createFriendsWithChat == "CODE"
            self.cr.secretChatAllowed = canChat
            if base.logPrivateInfo:
                self.notify.info("CREATE_FRIENDS_WITH_CHAT from game server login: %s %s" % (createFriendsWithChat, canChat))
            self.chatCodeCreationRule = responseData.get('chatCodeCreationRule')
            self.cr.chatChatCodeCreationRule = self.chatCodeCreationRule
            if base.logPrivateInfo:
                self.notify.info("Chat code creation rule = %s" % self.chatCodeCreationRule)
            self.cr.secretChatNeedsParentPassword = self.chatCodeCreationRule == "PARENT"
            serverTime = responseData.get('serverTime')
            self.cr.serverTimeUponLogin = serverTime
            self.cr.clientTimeUponLogin = now
            self.cr.globalClockRealTimeUponLogin = globalClock.getRealTime()
            if hasattr(self.cr, "toontownTimeManager"):
                self.cr.toontownTimeManager.updateLoginTimes(serverTime, now, self.cr.globalClockRealTimeUponLogin)
            serverDelta = serverTime - now
            self.cr.setServerDelta(serverDelta)
            self.notify.setServerDelta(serverDelta, 28800)
            access = responseData.get('access')
            self.isPaid = access == "FULL"
            self.cr.parentPasswordSet = self.isPaid
            self.cr.setIsPaid(self.isPaid)
            if self.isPaid:
                launcher.setPaidUserLoggedIn()
            if base.logPrivateInfo:
                self.notify.info("Paid from game server login: %s" % self.isPaid)
            WhiteListResponse = responseData.get('WhiteListResponse')
            if WhiteListResponse == "YES":
                self.cr.whiteListChatEnabled = 1
            else:
                self.cr.whiteListChatEnabled = 0
            self.lastLoggedInStr = responseData.get('lastLoggedInStr')
            self.cr.lastLoggedIn = datetime.now()
            if hasattr(self.cr, "toontownTimeManager"):
                self.cr.lastLoggedIn = self.cr.toontownTimeManager.convertStrToToontownTime(self.lastLoggedInStr)
            accountDaysFromServer = responseData.get('accountDays')
            if accountDaysFromServer is not None:
                self.cr.accountDays = self.parseAccountDays(accountDaysFromServer)
            else:
                self.cr.accountDays = 100000
            self.toonAccountType = responseData.get('toonAccountType')
            if self.toonAccountType == "WITH_PARENT_ACCOUNT":
                self.cr.withParentAccount = True
            elif self.toonAccountType == "NO_PARENT_ACCOUNT":
                self.cr.withParentAccount = False
            else:
                self.notify.error("unknown toon account type %s" % self.toonAccountType)
            if base.logPrivateInfo:
                self.notify.info("toonAccountType=%s" % self.toonAccountType)
            self.userName = responseData.get('userName')
            self.cr.userName = self.userName
            self.notify.info("Login response return code %s" % returnCode)
            if returnCode == 0:
                self.__handleLoginSuccess()
            elif returnCode == -13:
                self.notify.info("Period Time Expired")
                self.fsm.request("showLoginFailDialog", [OTPLocalizer.LoginScreenPeriodTimeExpired])
            else:
                self.notify.info("Login failed: %s" % errorString)
                messenger.send(self.doneEvent, [{'mode': 'reject'}])
