<?php

namespace Tobuli\History;

use phpDocumentor\Reflection\Types\Boolean;
use Tobuli\History\Stats\Stat;

class StatContainer
{
    protected $list = [];

    /**
     * @return Stat[]
     */
    public function all()
    {
        return $this->list;
    }

    public function keys()
    {
        return array_keys($this->list);
    }

    public function set($key, Stat $stat)
    {
        if ( ! empty($this->list[$key]))
            throw new \Exception("DeviceHistory stat '$key' already set");

        $this->list[$key] = $stat;
    }

    /**
     * @return Stat
     */
    public function get($key)
    {
        return $this->list[$key];
    }

    /**
     * @return Boolean
     */
    public function has($key)
    {
        return array_key_exists($key, $this->list);
    }

    public function apply($key, $value)
    {
        $this->get($key)->apply($value);
    }

    public function copy($stats)
    {
        foreach($stats as $key => $stat)
            $this->set($key, $stat);
    }

    /**
     * @return Stat[]
     */
    public function like($prefix)
    {
        return array_filter($this->list, function($stat, $key) use ($prefix){
            return starts_with($key, $prefix);
        }, ARRAY_FILTER_USE_BOTH);
    }

    public function _clone($stats)
    {
        foreach($stats as $key => $stat)
            $this->set($key, clone $stat);
    }

    /**
     * @return Stat[]
     */
    public function except($keys)
    {
        return array_filter($this->list, function($stat, $key) use ($keys){
            return ! in_array($key, $keys);
        }, ARRAY_FILTER_USE_BOTH);
    }

    /**
     * @return Stat[]
     */
    public function only($keys)
    {
        return array_filter($this->list, function($stat, $key) use ($keys){
            return in_array($key, $keys);
        }, ARRAY_FILTER_USE_BOTH);
    }

    /**
     * @return string
     */
    public function human($key)
    {
        if ( ! $this->has($key))
            return '-';

        return $this->get($key)->human()->get();
    }

    public function applyContainer(StatContainer $container)
    {
        $this->applyArray($container->all());
    }

    public function applyArray(array $array)
    {
        foreach ($array as $key => $stat)
        {
            if ( ! $this->has($key))
                $this->set($key, $stat);
            else
                $this->apply($key, $stat->value());
        }
    }

    public function __destruct()
    {
        unset($this->list);
    }
}