<?php
namespace nulib\schema\types;

use Exception;
use nulib\schema\_scalar\ScalarWrapper;
use nulib\schema\Schema;
use nulib\tests\TestCase;

class strTest extends TestCase {
  function commonTests($wrapper, &$value, callable $wrapperSetter): void {
    $wrapper->set("");
    self::assertSame("", $wrapper->get());
    self::assertSame("", $value);

    $wrapper->set(" ");
    self::assertSame("", $wrapper->get());
    self::assertSame("", $value);

    $wrapper->set("a");
    self::assertSame("a", $wrapper->get());
    self::assertSame("a", $value);

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

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

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

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

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

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

  function testStr() {
    /** @var ScalarWrapper $wrapper */
    Schema::nw($value, null, "string", $schema, $wrapper);
    $wrapperSetter = function($value) use($wrapper) {
      return function() use($wrapper, $value) {
        $wrapper->set($value);
      };
    };

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

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

    $this->commonTests($wrapper, $value, $wrapperSetter);
  }

  function testRequiredStr() {
    /** @var ScalarWrapper $wrapper */
    Schema::nw($value, null, [
      "string", null,
      "required" => true,
    ], $schema, $wrapper);
    $wrapperSetter = function($value) use($wrapper) {
      return function() use($wrapper, $value) {
        $wrapper->set($value);
      };
    };

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

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

    $this->commonTests($wrapper, $value, $wrapperSetter);
  }

  function testNstr() {
    /** @var ScalarWrapper $wrapper */
    Schema::nw($value, null, "?string", $schema, $wrapper);
    $wrapperSetter = function($value) use($wrapper) {
      return function() use($wrapper, $value) {
        $wrapper->set($value);
      };
    };

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

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

    $this->commonTests($wrapper, $value, $wrapperSetter);
  }

  function testRequiredNstr() {
    /** @var ScalarWrapper $wrapper */
    Schema::nw($value, null, [
      "?string", null,
      "required" => true,
    ], $schema, $wrapper);
    $wrapperSetter = function($value) use($wrapper) {
      return function() use($wrapper, $value) {
        $wrapper->set($value);
      };
    };

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

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

    $this->commonTests($wrapper, $value, $wrapperSetter);
  }
}
