<?php
namespace nur\sery\schema\types;

use Exception;
use nulib\tests\TestCase;
use nur\sery\wip\schema\_scalar\ScalarValue;
use nur\sery\wip\schema\Schema;

class strTest extends TestCase {
  function commonTests($destv, &$dest, callable $destvSetter): void {
    $destv->set("");
    self::assertSame("", $destv->get());
    self::assertSame("", $dest);

    $destv->set(" ");
    self::assertSame(" ", $destv->get());
    self::assertSame(" ", $dest);

    $destv->set("a");
    self::assertSame("a", $destv->get());
    self::assertSame("a", $dest);

    $destv->set("12");
    self::assertSame("12", $destv->get());

    $destv->set(" 12 ");
    self::assertSame(" 12 ", $destv->get());

    $destv->set(12);
    self::assertSame("12", $destv->get());

    $destv->set(12.34);
    self::assertSame("12.34", $destv->get());

    $destv->set(true);
    self::assertSame("1", $destv->get());

    self::assertException(Exception::class, $destvSetter([]));
    self::assertException(Exception::class, $destvSetter(["a"]));
  }

  function testStr() {
    /** @var ScalarValue $destv */
    Schema::nv($destv, $dest, null, $schema, "string");
    $destvSetter = function($value) use($destv) {
      return function() use($destv, $value) {
        $destv->set($value);
      };
    };

    self::assertException(Exception::class, $destvSetter(null));

    // valeur non requise donc retourne null
    $destv->set(false);
    self::assertNull($destv->get());

    $this->commonTests($destv, $dest, $destvSetter);
  }

  function testRequiredStr() {
    /** @var ScalarValue $destv */
    Schema::nv($destv, $dest, null, $schema, [
      "string", null,
      "required" => true,
    ]);
    $destvSetter = function($value) use($destv) {
      return function() use($destv, $value) {
        $destv->set($value);
      };
    };

    self::assertException(Exception::class, $destvSetter(null));

    // valeur requise donc lance une exception
    self::assertException(Exception::class, $destvSetter(false));

    $this->commonTests($destv, $dest, $destvSetter);
  }

  function testNstr() {
    /** @var ScalarValue $destv */
    Schema::nv($destv, $dest, null, $schema, "?string");
    $destvSetter = function($value) use($destv) {
      return function() use($destv, $value) {
        $destv->set($value);
      };
    };

    $destv->set(null);
    self::assertNull($destv->get());
    self::assertNull($dest);
    self::assertSame("", $destv->format());

    // valeur non requise donc retourne null
    $destv->set(false);
    self::assertNull($destv->get());

    $this->commonTests($destv, $dest, $destvSetter);
  }

  function testRequiredNstr() {
    /** @var ScalarValue $destv */
    Schema::nv($destv, $dest, null, $schema, [
      "?string", null,
      "required" => true,
    ]);
    $destvSetter = function($value) use($destv) {
      return function() use($destv, $value) {
        $destv->set($value);
      };
    };

    $destv->set(null);
    self::assertNull($destv->get());
    self::assertNull($dest);
    self::assertSame("", $destv->format());

    // valeur requise donc lance une exception
    self::assertException(Exception::class, $destvSetter(false));

    $this->commonTests($destv, $dest, $destvSetter);
  }
}
