<?php
namespace boru\ai\Conversation;

class Conversation
{
    /** @var ConversationReference */
    protected $reference;

    /** @var string|null */
    protected $provider;

    /** @var string|null */
    protected $model;

    /** @var array */
    protected $metadata = array();

    /** @var array */
    protected $storage = array();

    /** @var ConversationMemory|null */
    protected $memory;

    /** @var Turn[] */
    protected $turns = array();

    public function __construct(ConversationReference $reference = null)
    {
        $this->reference = $reference ? $reference : new ConversationReference();
    }

    public function reference(ConversationReference $reference = null)
    {
        if ($reference !== null) {
            $this->reference = $reference;
            return $this;
        }
        return $this->reference;
    }

    public function provider($value = null)
    {
        if ($value !== null) {
            $this->provider = (string)$value;
            return $this;
        }
        return $this->provider;
    }

    public function model($value = null)
    {
        if ($value !== null) {
            $this->model = (string)$value;
            return $this;
        }
        return $this->model;
    }

    public function addTurn(Turn $turn)
    {
        $this->turns[] = $turn;
        return $this;
    }

    public function turns($turns = null)
    {
        if ($turns !== null) {
            $this->turns = array();
            foreach ((array)$turns as $turn) {
                if ($turn instanceof Turn) {
                    $this->turns[] = $turn;
                }
            }
            return $this;
        }
        return $this->turns;
    }

    public function latestTurn()
    {
        if (empty($this->turns)) {
            return null;
        }
        return $this->turns[count($this->turns) - 1];
    }

    public function metadata($key = null, $value = null)
    {
        if ($key === null) {
            return $this->metadata;
        }
        if (is_array($key)) {
            $this->metadata = $key;
            return $this;
        }
        if (func_num_args() > 1) {
            $this->metadata[$key] = $value;
            return $this;
        }
        return isset($this->metadata[$key]) ? $this->metadata[$key] : null;
    }

    public function storage($key = null, $value = null)
    {
        if ($key === null) {
            return $this->storage;
        }
        if (is_array($key)) {
            $this->storage = $key;
            return $this;
        }
        if (func_num_args() > 1) {
            $this->storage[$key] = $value;
            return $this;
        }
        return isset($this->storage[$key]) ? $this->storage[$key] : null;
    }

    public function memory(ConversationMemory $memory = null)
    {
        if ($memory !== null) {
            $this->memory = $memory;
            return $this;
        }
        if (!$this->memory) {
            $this->memory = new ConversationMemory();
        }
        return $this->memory;
    }

    public function toArray()
    {
        $turns = array();
        foreach ($this->turns() as $turn) {
            $turns[] = $turn->toArray();
        }

        return array(
            'reference' => $this->reference()->toArray(),
            'provider' => $this->provider(),
            'model' => $this->model(),
            'metadata' => $this->metadata(),
            'memory' => $this->memory()->toArray(),
            'turns' => $turns,
        );
    }
}
