<?php
/**
 * Copyright 2020 Adobe
 * All Rights Reserved.
 *
 * NOTICE: Adobe permits you to use, modify, and distribute this file in
 * accordance with the terms of the Adobe license agreement accompanying
 * it.
 */
declare(strict_types=1);

namespace Magento\Mray\Index\Scanner\Probe\SubjectReader;

use Magento\Mray\Package\AbstractTree\ScannerSubjectReader;
use RuntimeException;
use function file_get_contents;
use function is_array;
use function json_decode;
use function json_last_error_msg;
use function sprintf;
use function str_replace;

class Json implements ScannerSubjectReader
{
    /**
     * @param string $path
     * @return array|mixed
     * @throws RuntimeException
     */
    public function read(string $path)
    {
        // phpcs:ignore Generic.PHP.NoSilencedErrors
        $content = @file_get_contents($path);
        if ($content === false) {
            if (strpos($path, 'composer') !== 0) {
                return null;
            }
            throw new RuntimeException(sprintf('Specified file "%s" does not exist or is not readable.', $path));
        }

        try {
            $data = json_decode($content, true, 512);
            if ($data === null && strpos($path, 'composer') === 0) {
                throw new RuntimeException(json_last_error_msg());
            }
        } catch (RuntimeException $e) {
            try {
                $data = json_decode($this->fixCommonJsonSyntaxIssues($content), true, 512);
                if ($data === null && strpos($path, 'composer') === 0) {
                    throw new RuntimeException(json_last_error_msg());
                }
            } catch (RuntimeException $e) {
                throw new RuntimeException(
                    sprintf('File "%s" does not contain valid JSON data: %s', $path, $e->getMessage()),
                    $e->getCode(),
                    $e
                );
            }
        }

        if (!is_array($data) && strpos($path, 'composer') === 0) {
            throw new RuntimeException(sprintf('Data from "%s" is not a structure', $path));
        }
        return $data;
    }

    /**
     * @param string $content
     * @return string|string[]
     */
    private function fixCommonJsonSyntaxIssues(string $content)
    {
        return str_replace(
            [
                "\n", // multiline strings
                ', ]', // comma after last item ijn array or object
                ',]',
                ', }',
                ',}',
            ],
            [
                ' ',
                ' ]',
                ']',
                ' }',
                '}'
            ],
            $content
        );
    }
}
