import ballerina/http;
import ballerina/log;

listener http:Listener gotServiceEP = new(9090); // ballerina service endpoint
http:Client gotQuoteAPI = new("https://got-quotes.herokuapp.com/quotes");   // game of thrones API endpoint

@http:ServiceConfig {
    basePath: "/got"    // basepath for my service
}
service gotService on gotServiceEP {
    @http:ResourceConfig {
        methods: ["GET"],
        path: "/quotes"     // resource path for getting a random quote.
    }
    resource function getQuote(http:Caller caller, http:Request request) {
        var gotQuoteResponse = gotQuoteAPI->get("/");  // get random quote.
        if (gotQuoteResponse is http:Response) {
            http:Response quoteResponse = new;
                var quoteJson = gotQuoteResponse.getJsonPayload();
                if (quoteJson is json) {
                    quoteResponse.setPayload(untaint quoteJson);
                    var response = caller->respond(quoteResponse);
                    if (response is error) {
                        log:printError("unable to send response to client", err = response);
                    }
                }
        } else {
            http:Response errorResponse = new;
            errorResponse.statusCode = 500;
            json errPayload = { err: "unable to get quote: service error"};
            errorResponse.setPayload(errPayload);

            var response = caller->respond(errorResponse);
            if (response is error) {
                log:printError("unable to send response to client", err = response);
            }
        }
    }

    @http:ResourceConfig {
        methods: ["GET"],
        path: "/quotes/character/{character}"   // resource path for getting quote from a character.
    }
    resource function getQuoteFromCharacter(http:Caller caller, http:Request request, string character) {
        var validCharacter = validateCharacter(character);
        if (validCharacter is string) {
            var gotQuoteResponse = gotQuoteAPI->get("/?char=" + validCharacter);   // get quote from character.
            if (gotQuoteResponse is http:Response) {
                http:Response quoteResponse = new;
                var quoteJson = gotQuoteResponse.getJsonPayload();
                if (quoteJson is json) {
                    quoteResponse.setPayload(untaint quoteJson);
                    var response = caller->respond(quoteResponse);
                    if (response is error) {
                        log:printError("unable to send response to client", err = response);
                    }
                }
            } else {
                http:Response errorResponse = new;
                errorResponse.statusCode = 500;
                json errPayload = { err: "unable to get quote from character: service error"};
                errorResponse.setPayload(errPayload);

                var response = caller->respond(errorResponse);
                if (response is error) {
                    log:printError("unable to send response to client", err = response);
                }
            }
        } else {
            // if invalid character
            http:Response errorResponse = new;
            errorResponse.statusCode = 400;
            json errPayload = { err: string.convert(validCharacter.detail().description)};
            errorResponse.setPayload(errPayload);

            var response = caller->respond(errorResponse);
            if (response is error) {
                log:printError("unable to send response to client", err = response);
            }
        }
    }
}

# Validates character.
# 
# + character - Game of Thrones character.
# + return - Untainted character or error if invalid character.
function validateCharacter(string character) returns string|error {
    // refer https://github.com/wsizoo/game-of-thrones-quotes
    string[] characters = ["bronn", 
                            "brynden", 
                            "cersei", 
                            "hound", 
                            "jaime", 
                            "littlefinger", 
                            "olenna", 
                            "renly", 
                            "tyrion", 
                            "varys"];

    foreach var char in characters {
        if (char == character) {
            return untaint character;
        }
    }

    error invalidCharacterErr = error("INVALID_CHAR", { description: "invalid character found: " + untaint character });
    return invalidCharacterErr;
}