/**
* This file acts as an abstraction layer to the server.
*/

/*
 The path where the server is hosted, to provide the correct links.

 If the server runs under https://example.com/schafkopf
 then apiPath = "/schafkopf"
 */
const apiPath = "/schafkopf"

var useEnglishTexts = false

const headerKeyPassword = "password";
const headerKeyToken = "token";
const headerKeyName = "name";
const headerKeyMail = "email";
const headerKeyVisibility = "visibility";
const headerKeyAction = "action";

function webSocketPath() {
    const prefix = (window.location.protocol === "https:") ? "wss://" : "ws://"
    return prefix + window.location.host + apiPath + "/session/start"
}

async function performRegisterPlayerRequest(name, password, email) {
    return fetch(apiPath + "/player/register", {
        method: 'POST',
        headers: {
            [headerKeyName]: name,
            [headerKeyPassword]: password,
            [headerKeyMail]: email
        }
    })
    .then(convertServerResponse)
}

async function performDeletePlayerRequest(name, password) {
    return fetch(apiPath + "/player/delete", {
        method: 'POST',
        headers: {
            [headerKeyName]: name,
            [headerKeyPassword]: password,
        }
    })
    .then(convertServerResponse)
    .then(function(value) {})
}

async function performLoginPlayerRequest(name, password) {
    return fetch(apiPath + "/player/login", {
        method: 'POST',
        headers: {
            [headerKeyName]: name,
            [headerKeyPassword]: password,
        }
    })
    .then(convertServerResponse)
}

async function performLogoutRequest(token) {
    return fetch(apiPath + "/player/logout", {
        method: 'POST',
        headers: { [headerKeyToken]: token },
    })
    .then(convertServerResponse)
    .then(function(value) {})
}

async function resumeSessionRequest(token) {
    return fetch(apiPath + "/player/resume", {
        method: 'POST',
        headers: { [headerKeyToken]: token },
    })
    .then(convertServerResponse)
}

async function performGetCurrentTableRequest(token) {
    return fetch(apiPath + "/player/table", {
        method: 'POST',
        headers: { [headerKeyToken]: token },
    })
    .then(convertServerResponse)
    .then(convertJsonResponse)
}

async function performRecoveryEmailRequest(name) {
    return fetch(apiPath + "/player/password/reset", {
        method: 'POST',
        headers: { [headerKeyName] : name },
    })
    .then(convertServerResponse)
}

async function performResetPasswordRequest(token, password) {
    return fetch(apiPath + "/player/password/new", {
        method: 'POST',
        headers: { [headerKeyPassword] : password, [headerKeyToken] : token }
    })
    .then(convertServerResponse)
}

async function performCreateTableRequest(token, name, visibility) {
    const vis = visibility ? "public" : "private";
    return fetch(apiPath + "/table/create", {
        method: 'POST',
        headers: {
            [headerKeyVisibility]: vis,
            [headerKeyToken]: token,
            [headerKeyName]: name,
        }
    })
    .then(convertServerResponse)
    .then(convertJsonResponse)
}

async function performJoinTableRequest(tableId, token) {
    return fetch(apiPath + "/table/join", {
        method: 'POST',
        headers: {
            [headerKeyName]: tableId,
            [headerKeyToken]: token,
        }
    })
    .then(convertServerResponse)
    .then(convertJsonResponse)
}

async function performGetPublicTablesRequest(token) {
    return fetch(apiPath + "/tables/public", {
        method: 'POST',
        headers: { [headerKeyToken] : token }
    })
    .then(convertServerResponse)
    .then(convertJsonResponse)
}

async function performLeaveTableRequest(token) {
    return fetch(apiPath + "/table/leave", {
        method: 'POST',
        headers: { [headerKeyToken] : token },
    })
    .then(convertServerResponse)
    .then(function(value) {})
}

async function performPlayerActionRequest(token, action) {
    return fetch(apiPath + "/player/action", {
        method: 'POST',
        headers: {
            [headerKeyToken] : token,
            [headerKeyAction] : action,
        },
    })
    .then(convertServerResponse)
    .then(function(value) {})
}

async function performPlayCardRequest(token, card) {
    return fetch(apiPath + "/player/card", {
        method: 'POST',
        headers: {
            [headerKeyToken] : token,
            [headerKeyAction] : card,
        },
    })
    .then(convertServerResponse)
    .then(function(value) {})
}

function convertServerResponse(response) {
    switch (response.status) {
        case 200: // Success
        return response.text()
        case 400: // Bad request
        throw Error("The request was malformed")
        case 401: // Unauthorized (Invalid session token)
        throw Error("Please log in again")
        case 403: // Forbidden
        throw Error("Invalid username or password")
        case 404: // Not found
        throw Error("Path not found")
        case 410: // Gone
        throw Error("The table could not be found")
        case 406: // notAcceptable
        throw Error("The password or name is too long")
        case 409: // Conflict
        throw Error("A user with the same name is already registered")
        case 417: // Expectation failed
        throw Error("The table is already full and can't be joined")
        case 424: // Failed dependency
        throw Error("The request couldn't be completed")
        default: 
        throw Error("Unexpected response: " + response.statusText)
    }
}

function convertJsonResponse(text) {
    if (text == "") {
        return null;
    }
    return JSON.parse(text);
}

// The state identifiers for all player states
const stateCanDouble = "canDouble"
const stateDidDouble = "doubled"
const stateIsDisconnected = "offline"
const stateMustBid = "bidder"
const stateDidFold = "fold"
const stateDidBid = "bid"
const stateIsGameSelector = "selects"
const stateIsWeddingOfferer = "wedding"
const stateIsCalled = "called"
const stateDidRaise = "raised"
const stateLeadsGame = "leads"
const stateIsWinner = "winner"
const stateIsLooser = "looser"

function convertStateToString(state) {
    switch (state) {
        case stateCanDouble:
        return useEnglishTexts ? "Can double" : "Kann legen"
        case stateDidDouble:
        return useEnglishTexts ? "Doubled" : "Leger"
        case stateIsDisconnected:
        return useEnglishTexts ? "Disconnected" : "Abwesend"
        case stateMustBid:
        return useEnglishTexts ? "Must bid": "Muss ansagen"
        case stateDidFold:
        return useEnglishTexts ? "Fold" : "Weg"
        case stateDidBid:
        return useEnglishTexts ? "Wants to play" : "Spielt"
        case stateIsGameSelector:
        return useEnglishTexts ? "Selects game" : "Wählt Spiel"
        case stateIsWeddingOfferer:
        return useEnglishTexts ? "Offers wedding" : "Hochzeit"
        case stateIsCalled:
        return useEnglishTexts ? "Called" : "Gerufen"
        case stateDidRaise:
        return useEnglishTexts ? "Raised" : "Schuss"
        case stateLeadsGame:
        return useEnglishTexts ? "Player" : "Spieler"
        case stateIsWinner:
        return useEnglishTexts ? "Winner" : "Hat gewonnen"
        case stateIsLooser:
        return useEnglishTexts ? "Looser" : "Hat verloren"
        default:
        return state
    }
}
