Code viewer for World: Assignment 2: Foundations
// ENTER API_KEY HERE

let API_KEY = "";

// END

const characterVoiceMap = {
    'Onyx': 'onyx',
    'Orion': 'shimmer',
    'Cyrus': 'echo',
};


const history = [
    {
        'character': "Orion",
        'message': "You know, Onyx, Cyrus, we've danced through hell together, haven't we? But now, here we are, prisoners of our own making. My loyalty, an unbreakable tether to duty, has led us to this cosmic prison hurtling towards the very flames we once embraced as our salvation. Funny how fate works its twisted magic."
    }
];

const playAudio = (audio, onEnd) => {
    try {
        const audioURL = URL.createObjectURL(audio);
        const audioElement = new Audio(audioURL);
        audioElement.play();
        audioElement.onended = () => {
            onEnd();
        };
    }
    catch (error) {
        console.error(error);
    }
};

const getAudio = async (text, voice, API_KEY) => {
    try {
        const url = 'https://api.openai.com/v1/audio/speech';

        const response = await fetch(url, {
            method: 'POST',
            headers: {
                'Authorization': `Bearer ${API_KEY}`,
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({
                model: 'tts-1',
                input: text,
                voice: voice,
            }),
        });

        if (!response.ok) {
            console.error(response);
            throw new Error('Network response was not ok');
        }

        const data = await response.blob();
        return data;
    } catch (error) {
        console.error(error);
        return error;
    }
};

const callChatAPI = async (userInput, history, API_KEY) => {
    var myHeaders = new Headers();
    myHeaders.append("Content-Type", "application/json");
    myHeaders.append("Access-Control-Allow-Origin", "*");

    var raw = JSON.stringify({
        "key": API_KEY,
        "userInput": userInput,
        history: history.map((message) => {
            return message.character + ": " + message.message + "\n";
        })[0]
    })

    console.log(raw);

    var requestOptions = {
        method: 'POST',
        headers: myHeaders,
        body: raw,
        redirect: 'follow'
    };

    try {
        const response = await fetch("https://ai-backend-seven.vercel.app/api/openai", requestOptions);
        if (!response.ok) {
            console.error(response);
            return false;
        }
        const data = await response.json();
        console.log(data);
        return data;
    } catch (error) {
        console.error(error);
        return false;
    }
}


// const API_KEY = prompt("API Key: ");


var characterInputDiv = document.createElement('div');
characterInputDiv.id = 'character-input-div';
characterInputDiv.style.position = 'absolute';
characterInputDiv.style.top = '50%';
characterInputDiv.style.left = '50%';
characterInputDiv.style.transform = 'translate(-50%, -50%)';
characterInputDiv.style.zIndex = 9999;
characterInputDiv.style.backgroundColor = '#00000066';
characterInputDiv.style.color = '#ffffff';
characterInputDiv.style.border = 'none';
characterInputDiv.style.outline = 'none';
characterInputDiv.style.padding = '8px';
characterInputDiv.style.borderRadius = '8px';
characterInputDiv.style.fontFamily = 'monospace';
characterInputDiv.style.fontSize = '14px';
characterInputDiv.style.fontWeight = 'bold';
characterInputDiv.style.display = 'flex';
characterInputDiv.style.alignItems = 'start';
characterInputDiv.style.justifyContent = 'start';
characterInputDiv.style.flexDirection = 'column';
characterInputDiv.style.gap = '8px';
characterInputDiv.style.width = '400px';
document.body.appendChild(characterInputDiv);

const messagesElement = document.createElement('div');
messagesElement.style.display = 'flex';
messagesElement.style.alignItems = 'start';
messagesElement.style.justifyContent = 'start';
messagesElement.style.flexDirection = 'column';
messagesElement.style.gap = '8px';
messagesElement.style.width = 'fit-content';
messagesElement.style.maxHeight = '300px';
messagesElement.style.width = '100%';
messagesElement.style.wordWrap = 'break-word';
messagesElement.style.backgroundColor = '#00000066';
messagesElement.style.borderRadius = '8px';
characterInputDiv.appendChild(messagesElement);


var characterInput = document.createElement('input');
characterInput.type = 'text';
characterInput.id = 'character-character-input';

characterInput.style.zIndex = 9999;
characterInput.style.backgroundColor = '#00000088';
characterInput.style.color = '#ffffff';
characterInput.style.border = 'none';
characterInput.style.outline = 'none';
characterInput.style.padding = '4px 8px';
characterInput.style.width = '96%';
characterInput.style.borderRadius = '8px';
characterInput.style.fontFamily = 'monospace';
characterInput.placeholder = 'Respond as Onyx...';
characterInput.focus();
characterInputDiv.appendChild(characterInput);

// add a listener to the input

function messageElement(message) {
    const messageElement = document.createElement('div');
    messageElement.style.color = '#ffffff';
    messageElement.style.border = 'none';
    messageElement.style.outline = 'none';
    messageElement.style.width = '96%';
    messageElement.style.backgroundColor = '#00000044';
    messageElement.style.borderRadius = '8px';
    messageElement.style.fontFamily = 'monospace';
    messageElement.style.fontSize = '14px';
    messageElement.style.fontWeight = 'bold';
    messageElement.style.padding = '8px';
    messageElement.innerText = message;
    messagesElement.appendChild(messageElement);
}

var showInput = true;

function inputs() {
    if (showInput) {
        characterInputDiv.style.display = 'flex';
    } else {
        characterInputDiv.style.display = 'none';
    }
}

characterInput.addEventListener('keydown', async function (e) {
    if (e.key === 'Enter') {
        var characterInputValue = characterInput.value;
        characterInput.value = '';
        console.log(characterInputValue);

        history.push({
            'character': "Onyx",
            'message': characterInputValue
        });

        messageElement("Onyx: " + characterInputValue);

        const response = await callChatAPI(characterInputValue, history, API_KEY);
        if (response) {
            showInput = false;
            history.push({
                'character': response['character'],
                'message': response['output']
            });
            messageElement(response['character'] + ": " + response['output']);
            showInput = true;
        }

        // const audio = await getAudio(characterInputValue, "onyx", API_KEY);
        // playAudio(audio, async () => {
        // });
    }
});

inputs();