<?php
namespace Newland\NeosCommon\Service;

/*
 * This file is part of the "neos-common" package.
 *
 * For the full copyright and license information, please read the
 * LICENSE.txt file that was distributed with this source code.
 */

use Neos\Flow\Property\Exception\InvalidPropertyException;

class RecordService
{
    /** @param object $record */
    public function getProperty($record, string $property): string
    {
        try {
            if (strpos($property, '.') !== false) {
                $propertyValue = $this->resolveDotNotation($record, $property);
            } else {
                $method = 'get' . ucfirst($property);
                $propertyValue = $record->$method();
            }
        } catch (\Exception $e) {
            throw new InvalidPropertyException(
                'Property could not be resolved. Check the scenario configuration.'
            );
        }

        return (string) $propertyValue;
    }

    /**
     * @param object $record
     * @param string $property
     * @return string
     */
    public function resolveDotNotation($record, string $property): string
    {
        try {
            $bits = explode('.', $property);
            $containerProperty = (string) array_shift($bits);
            $method = 'get' . ucfirst($containerProperty);
            $container = $record->$method();
            $childProperty = (string) array_shift($bits);
            if (is_numeric($childProperty)) {
                if (!(is_array($container) || $container instanceof \ArrayAccess)
                    || !isset($container[$childProperty])
                ) {
                    throw new InvalidPropertyException('Invalid array offset.');
                }
                // if it's a collection of some sort, we get the element by index
                $container = $container[$childProperty];
                $childProperty = (string) array_shift($bits);
            }
            $method = 'get' . ucfirst($childProperty);
            return $container->$method();
        } catch (\Exception $e) {
            return '';
        }
    }

    /** @param object $record */
    public function getPropertyWithFallback($record, array $properties): string
    {
        foreach ($properties as $property) {
            $value = $this->getProperty($record, $property);
            if ($value) {
                return $value;
            }
        }
        return '';
    }
}
