
// The web socket to connect to the server
var socket = null;
var tableId = null;
var activePlayer = null;

function closeSocketIfNeeded() {
    if (socket) {
        socket.close()
        didCloseSocket()
    }
}

function didLeaveTable() {
    tableId = null
}

function didCloseSocket() {
    socket = null
}

function setTableId(table) {
    tableId = table
}

function showLoginWithError(error) {
    showLoginWithText(error.message)
}

function showBlankLogin() {
    showLoginWithText("")
}

function showLoginWithText(text) {
    closeSocketIfNeeded()
    didLeaveTable()
    clearLoginPassword()
    clearLoginName()
    deleteSessionToken()
    showLoginElements()
    setLoginError(text)
}

function showTableOrList(table) {
    if (table == null) {
        didLeaveTable()
        showTableListElements()
        closeSocketIfNeeded()
        refreshTables()
        // TODO: Show table list, refresh
        return
    }
    
    const token = getSessionToken()
    if (token == null) {
        showBlankLogin()
        return
    }
    clearTableName()
    setTableId(table.id)
    showGameElements()
    updateTableInfo(table)
    openSocket(token)
}

function registerUser() {
    createSession(performRegisterPlayerRequest)
}

function loginUser() {
    createSession(performLoginPlayerRequest)
}

function createSession(inputFunction) {
    const username = getLoginName()
    const password = getLoginPassword()
    if (username == "") {
        showLoginWithText("Please enter your user name")
        return
    }
    if (password == "") {
        showLoginWithText("Please enter a password")
        return
    }
    inputFunction(username, password)
    .then(function(token) {
        setSessionToken(token)
        setPlayerName(username)
        loadCurrentTable(token)
    }).catch(showLoginWithError)
}

function logoutUser() {
    const token = getSessionToken()
    if (token == null) {
        showBlankLogin()
        return
    }
    performLogoutRequest(token)
    .then(function() {
        showBlankLogin()
    }).catch(showLoginWithError)
}

function deletePlayerAccount() {
    const name = getPlayerName()
    const password = getLoginPassword()
    
    performDeletePlayerRequest(name, password)
    .then(showBlankLogin)
    .catch(showLoginWithError)
}

function loadExistingSession() {
    if (debugMode) {
        showDebugLogins()
    }
    const token = getSessionToken()
    if (token == null) {
        showBlankLogin()
        return
    }
    resumeSessionRequest(token)
    .then(function(name) {
        setPlayerName(name)
        loadCurrentTable(token)
    }).catch(showLoginWithError)
}

function loadCurrentTable(token) {
    performGetCurrentTableRequest(token)
    .then(showTableOrList)
    .catch(showLoginWithError)
}

function createTable() {
    const tableName = getTableName()
    if (tableName == "") {
        return
    }
    const token = getSessionToken()
    if (token == null) {
        showBlankLogin()
        return
    }        
    const isVisible = getTableVisibility()
    performCreateTableRequest(token, tableName, isVisible)
    .then(showTableOrList)
    .catch(showLoginWithError)
}

function joinTable(tableId) {
    const token = getSessionToken()
    if (token == null) {
        showBlankLogin()
        return
    }
    performJoinTableRequest(tableId, token)
    .then(showTableOrList)
    .catch(showLoginWithError)
}

function leaveTable() {
    const token = getSessionToken()
    if (token == null) {
        showBlankLogin()
        return
    }
    performLeaveTableRequest(token)
    .then(function() {
        showTableOrList(null)
    })
    .catch(showLoginWithError)
}

function openSocket(token) {
    socket = new WebSocket(((window.location.protocol === "https:") ? "wss://" : "ws://") + window.location.host + "/session/start")
    
    socket.onopen = function(e) {
        socket.send(token);
        showConnectedState()
    };
    
    socket.onmessage = function(event) {
        const table = convertJsonResponse(event.data)
        updateTableInfo(table)
    };
    
    socket.onclose = function(event) {
        if (event.wasClean) {
            
        } else {
            // e.g. server process killed or network down
            // event.code is usually 1006 in this case
            // TODO: Retry several times to open socket,
            // stop after too many failed attempts
        }
        didCloseSocket()
        showDisconnectedState()
    };
    
    socket.onerror = function(error) {
        // error.message
    };
}

function refreshTables() {
    const token = getSessionToken()
    if (token == null) {
        showBlankLogin()
        return
    }
    performGetPublicTablesRequest(token)
    .then(processTableList)
    .catch(showLoginWithError)
}

function processTableList(tables) {
    var html = ""
    for (let i = 0, len = tables.length; i < len; i++) {
        tableInfo = tables[i]
        html += "<div class=\"table-row\">"
        if (tableInfo.players.length < 4) {
            html += "<button class=\"table-join-btn\" onclick=\"joinTable('" + tableInfo.id + "')\">Join</button>"
        } else {
            html += "<button class=\"table-join-btn\" disabled>Full</button>"
        }
        html += "<div class=\"table-title\">" + tableInfo.name + "</div>"
        if (tableInfo.players.length == 0) {
            html += "<div class=\"table-subtitle\">No players</div>"
        } else {
            const names = tableInfo.players.join(", ")
            html += "<div class=\"table-subtitle\">" + names + "</div>"
        }
        html += "</div>" // table-row 
    }
    setTableListContent(html)
}

function dealCards() {
    const token = getSessionToken()
    if (token == null) {
        showBlankLogin()
        return
    }
    performDealCardsRequest(token)
    .catch(showLoginWithError)
}

function playCard(card) {
    const token = getSessionToken()
    if (token == null) {
        showBlankLogin()
        return
    }
    performPlayCardRequest(token, card)
    .catch(function(error) {
        console.log(error)
    })
}