<?php
namespace boru\boruai\Openai\Models;

use boru\boruai\Openai\Models\BaseModel;
use boru\boruai\Openai\OpenAIChat;
use boru\boruai\Openai\OpenAIMessage;
use boru\output\Output;

class Messages extends BaseModel {

    /** @var OpenAIMessage[] */
    private $body = [];


    public function __construct($messages=[]) {
        if(!empty($messages)) {
            $this->body = $messages;
        }
    }

    public function count() {
        return count($this->body);
    }

    /**
     * Get or set the messages
     * @param array $messages
     * @return array
     */
    public function messages($messages=null) {
        if($messages !== null) {
            if(is_array($messages)) {
                $this->body = [];
                foreach($messages as $message) {
                    if($message instanceof OpenAIMessage) {
                        $this->body[] = $message;
                    } else {
                        $this->body[] = new OpenAIMessage($message);
                    }
                }
            }
        }
        return $this->body;
    }

    /**
     * Get a message from the list
     * @param int $i
     * @param bool $asObject
     * @return OpenAIMessage|OpenAIMessage[]|array
     */
    public function get($i=-1,$asObject=false) {
        if($i >= 0) {
            return $asObject ? $this->body[$i] : $this->body[$i]->forChat();
        }
        return $asObject ? $this->body : $this->toArray();
    }

    /**
     * Add a message to the list
     * @param OpenAIMessage|array $message
     * @return OpenAIMessage
     */
    public function add($message) {
        if($message instanceof OpenAIMessage) {
            
        } else {
            $message = new OpenAIMessage($message);
        }
        $this->body[] = $message;
        return $message;
    }

    /**
     * Add a message to the list
     * @param mixed $role 
     * @param mixed $content 
     * @param array $attachments 
     * @param array $metadata 
     * @return OpenAIMessage
     */
    public function addMessage($role,$content,$attachments=[],$metadata=[]) {
        if(!$content instanceof Content) {
            $content = new Content($content);
        }
        $data = [
            "role" => $role,
            "content" => $content,
            "attachments" => $attachments,
            "metadata" => $metadata
        ];
        return $this->add($data);
    }


    public function addFile($fileIdOrPath,$type="file",$mimeType=null) {
        $message = new OpenAIMessage(["role"=>"user"]);
        $message->file($fileIdOrPath,$type,$mimeType);
        return $this->add($message);
    }

    /**
     * Convert the messages to an array
     * @param bool $forChat
     * @return array
     */
    public function toArray($forChat=true) {
        $data = [];
        if($forChat) {
            foreach($this->body as $message) {
                $data[] = $message->forChat();
            }
        } else {
            foreach($this->body as $message) {
                $data[] = $message->forThread();
            }
        }
        return $data;
    }

    public function compressor($excludeLastN=1,$startAt=2) {
        $compressor = new MessagesCompressor($this,$excludeLastN,$startAt);
        return $compressor;
    }
    public function compress($excludeLastN=1,$startAt=2) {
        $compressor = $this->compressor($excludeLastN,$startAt);
        $compressor->compress();
        $this->body = $compressor->messages();
    }
}