<?php
/**
 * Extended Data Dictionary
 *
 * @author Elze Kool <info@visualmedia.nl>
 */

namespace VisualM\TagManagerBundle\Util;

use VisualM\DataExtractBundle\Data\DataCollectorInterface;
use VisualM\DataExtractBundle\Data\DictionaryCollectorInterface;
use VisualM\DataExtractBundle\Data\TypeEnum;
use VisualM\TagManagerBundle\Content\MetaHelper;

/**
 * Extended Data Dictionary
 *
 * Extention to the Data Dictionary provided by the VisualMDataExtractBundle
 * allows adding static values
 *
 * @author Elze Kool <info@visualmedia.nl>
 */
class ExtendedDataDictionary
{
    /**
     * DictionaryCollector
     * @var DictionaryCollectorInterface
     */
    protected $dictionaryCollector;

    /**
     * Data Collector
     * @var DataCollectorInterface
     */
    protected $dataCollector;
    
    /**
     * Static data fields
     * @var array
     */
    protected $staticData = [];

    /**
     * Constructor
     *
     * @param DictionaryCollectorInterface $dictionaryCollector Dictionary Collector
     * @param DataCollectorInterface       $dataCollector       Data Collector
     */
    public function __construct(DictionaryCollectorInterface $dictionaryCollector, DataCollectorInterface $dataCollector)
    {
        $this->dictionaryCollector = $dictionaryCollector;
        $this->dataCollector = $dataCollector;
    }

    /**
     * Get available fields
     *
     * @return array Available fields
     */
    public function getAvailableFields()
    {
        $fields = $this->dictionaryCollector->getAvailableFields([TypeEnum::STRING]);
        $merged_fields = array_merge($fields, array_keys($this->staticData));
        sort($merged_fields);
        return $merged_fields;
    }

    /**
     * Collect Data for Object
     *
     * @param object $object Object to collect data for
     *
     * @return MetaHelper self
     */
    public function pushObject($object)
    {
        $this->dataCollector->pushObject($object);
        return $this;
    }

    /**
     * Set Static Field Value
     *
     * @param string $field Field name
     * @param string $value Field value
     */
    public function setStaticField($field, $value)
    {
        if (preg_match('/^([a-z_]+)(\.([a-z_]+))?$/', $field) == 0) {
            throw new RuntimeException(sprintf(
                'Invalid field name "%s" provided for "%s", ' .
                'field names must be all lowercase, with optional underscore and seperated with a comma, ' .
                'fields can be global (no dot) or domain specific (with one(!) dot)',
                $field,
                get_class($this)
            ));
        }
        $this->staticData[$field] = $value;
    }

    /**
     * Get Data (static and collected)
     *
     * @return array Data
     */
    public function getData()
    {
        $data = $this->dataCollector->getCollected([ TypeEnum::STRING ]);
        $merged_data = array_merge($this->staticData, $data);

        foreach($this->getAvailableFields() as $available) {

            list($head, $sub) = array_merge(explode('.', $available), [ null ]);

            if (!array_key_exists($head, $merged_data)) {
                $merged_data[$head] = ($sub === null) ? null : [];
            }

            if (($sub !== null) AND is_array($merged_data[$head]) AND !array_key_exists($sub, $merged_data[$head])) {
                $merged_data[$head][$sub] = null;
            }



        }
        return $merged_data;
    }


}
