<?php
namespace nur\sery\ext;

use Exception;
use nur\sery\ext\json\JsonException;
use nur\sery\file;
use nur\sery\os\IOException;

/**
 * Class json: gestion de données json
 */
class json {
  static function decode(string $json, int $flags=0) {
    return json_decode($json, true, 512, $flags);
  }

  static function encode($data, int $flags=0): string {
    $flags |= JSON_UNESCAPED_SLASHES + JSON_UNESCAPED_UNICODE;
    return json_encode($data, $flags);
  }

  static function check(string $json, &$data=null): bool {
    try {
      $data = self::decode($json, JSON_THROW_ON_ERROR);
      return true;
    } catch (Exception $e) {
      return false;
    }
  }

  /**
   * @throws IOException si une erreur de lecture s'est produite
   */
  static final function load($input): array {
    $contents = file::reader($input)->getContents();
    return JsonException::ensure_json_value(self::decode($contents));
  }

  /** obtenir la valeur JSON correspondant au corps de la requête POST */
  static final function post_data() {
    $content = file_get_contents("php://input");
    return JsonException::ensure_json_value(self::decode($content));
  }

  /** envoyer $data au format JSON */
  static final function send($data, bool $exit=true): void {
    header("Content-Type: application/json");
    print self::encode($data);
    if ($exit) exit;
  }

  const INDENT_TABS = "\t";

  static final function with($data, ?string $indent=null): string {
    $json = self::encode($data, JSON_PRETTY_PRINT);
    if ($indent !== null) {
      $json = preg_replace_callback('/^(?: {4})+/m', function (array $ms) use ($indent) {
        return str_repeat($indent, strlen($ms[0]) / 4);
      }, $json);
    }
    return $json;
  }

  static final function dump($data, $output=null): void {
    file::writer($output)->putContents(self::with($data));
  }
}
