<?php
// Copyright (c) Pickware GmbH. All rights reserved.
// This file is part of software that is released under a proprietary license.
// You must not copy, modify, distribute, make publicly available, or execute
// its contents or parts thereof without express permission by the copyright
// holder, unless otherwise permitted by law.

namespace Shopware\Plugins\ViisonCommon\Structs;

/**
 * Handles struct collections. The main purpose of this class is
 * to provide a toArray method, which will traverse over all
 * structs in the collection and returns their array representations.
 */
class Collection implements \ArrayAccess, \IteratorAggregate, \Countable
{
    /**
     * @var array
     */
    private $container = [];

    public function __construct(array $container = [])
    {
        // By adding the values individually, we make sure that the contents have the correct data type (type check performed in method offsetSet)
        foreach ($container as $value) {
            $this[] = $value;
        }
    }

    /**
     * Implements the offsetSet method of the ArrayAccess interface.
     *
     * @param int $offset
     * @param Shopware\Plugins\ViisonCommon\Structs\Struct $value
     */
    public function offsetSet($offset, $value)
    {
        if (! is_a($value, 'Shopware\\Plugins\\ViisonCommon\\Structs\\Struct')) {
            throw new \InvalidArgumentException('Value must be of type "Shopware\\Plugins\\ViisonCommon\\Structs\\Struct".');
        }

        if ($offset === null) {
            $this->container[] = $value;
        } else {
            $this->container[$offset] = $value;
        }
    }

    /**
     * Implements the offsetExists method of the ArrayAccess interface.
     *
     * @param int $offset
     * @return bool true, if offset exists
     */
    public function offsetExists($offset)
    {
        return isset($this->container[$offset]);
    }

    /**
     * Implements the offsetUnset method of the ArrayAccess interface.
     *
     * @param int $offset
     */
    public function offsetUnset($offset)
    {
        unset($this->container[$offset]);
    }

    /**
     * Implements the offsetGet method of the ArrayAccess interface.
     *
     * @param int $offset
     */
    public function offsetGet($offset)
    {
        return isset($this->container[$offset]) ? $this->container[$offset] : null;
    }

    /**
     * Implements the getIterator method of the IteratorAggregate interface.
     */
    public function getIterator()
    {
        return new \ArrayIterator($this->container);
    }

    /**
     * Implements the count method of the Countable interface.
     */
    public function count()
    {
        return count($this->container);
    }

    /**
     * Returns the array representation of all structs in the collection.
     *
     * @return array
     */
    public function toArray()
    {
        $data = [];
        foreach ($this->container as $item) {
            $data[] = $item->toArray();
        }

        return $data;
    }
}
