<?php

namespace IZON\Thumber\Configuration;

/**
 * Description of Configuration
 *
 * @author lukas
 */
class Configuration implements \ArrayAccess {
    /**
     *
     * @var array
     */
    var $parameters = [];

    /**
     * 
     * @param array $defaultConfiguration
     */
    public function __construct(array $defaultConfiguration = []) {
        foreach($defaultConfiguration as $key => $value) {
            $this->set($key, $value);
        }
    }

    /**
     * 
     * @param mixed $key
     */
    public function get($key) {
        if(!$this->has($key)) {
            return null;
        }
        return $this->parameters[$key];
    }

    /**
     * 
     * @param mixed $key
     * @return bool
     */
    public function has($key): bool {
        return isset($this->parameters[$key]);
    }

    public function isNestedConfig($key): bool {
        return $this->has($key) && $this->get($key) instanceof static;
    }

    /**
     * 
     * @param mixed $key
     * @param mixed $value
     */
    public function set($key, $value) {
        if(is_array($value)) {
            $value = new static($value);
        }
        $this->parameters[$key] = $value;
    }

    /**
     * extends values of config
     * @param array $config
     */
    public function extend(array $config) {
        foreach($config as $key => $value) {
            $valueIsArray = is_array($value);
            $isConfig = $this->isNestedConfig($key);

            if($valueIsArray && $isConfig) {
                $this->parameters[$key]->extend($value);
            } else {
                $this->set($key, $value);
            }
        }
    }

    public function insertDefault(array $config) {
        foreach($config as $key => $value) {
            $valueIsArray = is_array($value);
            $keyExists = $this->has($key);
            $isConfig = $this->isNestedConfig($key);
            
            if($valueIsArray && $isConfig) {
                $this->parameters[$key]->insertDefault($value);
            } else if(!$keyExists) {
                $this->set($key, $value);
            }
        }
    }

    // -------------------------------------------------------------------------
    // ArrayAccess interface
    // -------------------------------------------------------------------------

    public function remove($key) {
        if($this->has($key)) {
            unset($this->parameters[$key]);
        }
    }

    public function offsetExists($offset): bool {
        return $this->has($offset);
    }

    public function offsetGet($offset) {
        return $this->get($offset);
    }

    public function offsetSet($offset, $value): void {
        $this->set($offset, $value);
    }

    public function offsetUnset($offset): void {
        $this->remove($offset);
    }

}

