export class ChatLogs {
    _logs = {
        persistent: {
            tokens: 0,
            msgs: [],
        },
        temporary: {
            tokens: 0,
            msgs: [],
        },
    };
    _tokensPerMsg = {
        persistent: [],
        temporary: [],
    };
    _functions = {
        tokens: 0,
        definitions: [],
    };
    constructor(logs, tokensPerMsg, functions) {
        if (logs) {
            this._logs = logs;
        }
        if (tokensPerMsg) {
            this._tokensPerMsg = tokensPerMsg;
        }
        if (functions) {
            this._functions = functions;
        }
    }
    get tokens() {
        return this._logs.persistent.tokens + this._logs.temporary.tokens + this._functions.tokens;
    }
    get messages() {
        return [...this._logs.persistent.msgs, ...this._logs.temporary.msgs];
    }
    get(type) {
        return this._logs[type];
    }
    getMsg(type, index) {
        return this._logs[type].msgs.at(index);
    }
    getMsgTokens(type, index) {
        const tokens = this._tokensPerMsg[type];
        if (index < 0 || index >= tokens.length) {
            throw Error('invalid index');
        }
        return tokens[index];
    }
    add(type, msgs, tokens) {
        if (msgs.length !== tokens.length) {
            throw Error('msgs & tokens must be equal size.');
        }
        this._logs[type].tokens += tokens.reduce((acc, cur) => acc + cur, 0);
        this._tokensPerMsg[type].push(...tokens);
        this._logs[type].msgs.push(...msgs);
    }
    insert(type, msgs, tokens, index) {
        this._logs[type].tokens += tokens.reduce((acc, cur) => acc + cur, 0);
        this._tokensPerMsg[type].splice(index, 0, ...tokens);
        this._logs[type].msgs.splice(index, 0, ...msgs);
    }
    addFunction(fn, tokens) {
        this._functions.tokens += tokens;
        this._functions.definitions.push(fn);
    }
    clone() {
        return new ChatLogs(JSON.parse(JSON.stringify(this._logs)), JSON.parse(JSON.stringify(this._tokensPerMsg)), JSON.parse(JSON.stringify(this._functions)));
    }
    toString() {
        return JSON.stringify(this, null, 2);
    }
    toJSON() {
        return {
            msgs: this._logs,
            functions: {
                tokens: this._functions.tokens,
                names: this._functions.definitions.map(d => d.name),
            },
        };
    }
    static from(persistentMsgs, temporaryMsgs, tokenizer) {
        const persistentTokens = persistentMsgs.map(x => (x.content ? tokenizer.encode(x.content).length : 0));
        const temporaryTokens = persistentMsgs.map(x => (x.content ? tokenizer.encode(x.content).length : 0));
        return new ChatLogs({
            persistent: {
                tokens: persistentTokens.reduce((a, b) => a + b, 0),
                msgs: persistentMsgs,
            },
            temporary: {
                tokens: temporaryTokens.reduce((a, b) => a + b, 0),
                msgs: temporaryMsgs,
            },
        }, {
            persistent: persistentTokens,
            temporary: temporaryTokens,
        });
    }
}
