package org.studiorailgun.conversation.llm;

import java.util.LinkedList;

import org.studiorailgun.kobold.KoboldRequest;
import org.studiorailgun.kobold.KoboldSymbols;

public class LLMConversation {
    
    /**
     * The participants in the conversation
     */
    LinkedList<Actor> participants;

    /**
     * The statements of the conversation
     */
    LinkedList<Statement> statements;

    /**
     * Number of statements to send in memory
     */
    static final int STATEMENTS_TO_SEND_IN_MEMORY = 10;

    /**
     * Constructor
     */
    public LLMConversation(){
        this.participants = new LinkedList<Actor>();
        this.statements = new LinkedList<Statement>();
    }

    /**
     * Adds a participant to the conversation
     * @param actor The new actor
     */
    public void addParticipant(Actor actor){
        this.participants.add(actor);
    }

    /**
     * Adds a statement to the conversation
     * @param statement The statement
     */
    public void addStatement(Statement statement){
        this.statements.add(statement);
        statement.setConversation(this);
    }

    /**
     * Requests a statement for the actor
     * @param actor The actor
     */
    public KoboldRequest generateStatementRequest(Actor actor){
        KoboldRequest rVal = null;
        String prompt = "";

        //memory portion
        prompt = prompt + "<|system|>\\n";
        prompt = prompt + "You are named " + actor.getName() + "\\n";
        prompt = prompt + "You are in a conversation with \\n";
        for(Actor participant : this.participants){
            if(participant != actor){
                prompt = prompt + participant.getName() + "\\n";
            }
        }
        prompt = prompt + "The most recent dialog in the conversation is\\n";
        int increments = 0;
        for(int i = this.statements.size() - 1; i >= 0 && increments < STATEMENTS_TO_SEND_IN_MEMORY; i--){
            Statement statement = this.statements.get(i);
            prompt = prompt + statement.getActor().getName() + ": " + statement.getContent() + "\\n";
            increments++;
        }
        prompt = prompt + "<|end|>\\n";

        //request new statement
        prompt = prompt + "<|user|>\\n";
        prompt = prompt + "What is the next thing " + actor.getName() + " should say?\\n";
        prompt = prompt + "Give me exactly the quote " + actor.getName() + " should say and nothing more.\\n";
        // prompt = prompt + "Do not describe the tone.\\n";
        prompt = prompt + "Do not explain the quote.\\n";
        prompt = prompt + "Do not give me dialog for any other character.\\n";
        prompt = prompt + "Do not describe what other characters should do.\\n";
        prompt = prompt + "Do not add notes.\\n";
        prompt = prompt + "Do not include ways to continue the conversation.\\n";
        prompt = prompt + "Do not include quotation marks.\\n";
        prompt = prompt + "<|end|>\\n";
        prompt = prompt + "<|assistant|>\\n";
        
        //construct actual request from prompt
        rVal = new KoboldRequest(prompt);
        return rVal;
    }

    /**
     * Pushes the result of a kobold request into the conversation stack
     * @param actor The actor that said the statement
     * @param request The request
     */
    public void pushbackRequest(Actor actor, KoboldRequest request){
        String rawResponse = request.getResponse();
        String parsed = rawResponse;
        //remove notes if they are detected
        if(KoboldSymbols.containsBannedSymbol(parsed)){
            parsed = KoboldSymbols.removeBannedSymbol(parsed);
        }

        //actually create and store statement
        Statement statement = new Statement(actor, parsed);
        this.addStatement(statement);
    }

}
