<?php declare(strict_types=1);
/*
 * irstea/php-cs-fixer-config - Jeux de règles pour php-cs-fixer.
 * Copyright (C) 2018-2020 IRSTEA
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 */

namespace Irstea\CS\Composer;

use Assert\Assertion;
use Irstea\CS\FileLocator\FileLocatorInterface;

/**
 * Class ComposerPackage.
 */
final class ComposerPackage implements ComposerPackageInterface
{
    /**
     * @var array|null
     */
    private $composerJson;

    /**
     * @var FileLocatorInterface
     */
    private $fileLocator;

    /**
     * ComposerPackage constructor.
     */
    public function __construct(FileLocatorInterface $fileLocator)
    {
        $this->fileLocator = $fileLocator;
    }

    /**
     * {@inheritdoc}
     */
    public function getName(): string
    {
        return $this->getKey('name', '');
    }

    /**
     * {@inheritdoc}
     */
    public function getDescription(): string
    {
        return $this->getKey('description', '');
    }

    /**
     * {@inheritdoc}
     */
    public function getRequiredPHPVersion(): float
    {
        $require = $this->getKey('require', []);
        if (
            isset($require['php'])
            && preg_match('/(?:>=?|\^|~)\s*([578]\.\d)/', $require['php'], $groups)
        ) {
            return (float) $groups[1];
        }

        return 5.6;
    }

    /**
     * {@inheritdoc}
     */
    public function getLicenses(): iterable
    {
        return (array) $this->getKey('license', 'proprietary');
    }

    /**
     * @param string $key
     * @param mixed  $default
     *
     * @throws \Assert\AssertionFailedException
     *
     * @return mixed|string|number|null
     */
    private function getKey($key, $default = null)
    {
        Assertion::string($key);

        $data = $this->getComposerJson();

        return \array_key_exists($key, $data) ? $data[$key] : $default;
    }

    private function getComposerJson(): array
    {
        return \is_array($this->composerJson) ? $this->composerJson : $this->readComposerJson();
    }

    /**
     * @throws \Assert\AssertionFailedException
     */
    private function readComposerJson(): array
    {
        $composerPath = $this->fileLocator->locate('composer.json');
        Assertion::notNull($composerPath, 'could not find composer.json');

        $content = file_get_contents($composerPath);
        Assertion::string($content, "could not read `$composerPath`");

        $this->composerJson = json_decode($content, true);
        Assertion::isArray($this->composerJson);

        return $this->composerJson;
    }
}