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

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

class floatTest extends TestCase {
  function commonTests($destv, &$dest, callable $destvSetter): void {
    $destv->set(12);
    self::assertSame(12.0, $destv->get());
    self::assertSame(12.0, $dest);
    self::assertSame("12", $destv->format());
    self::assertSame("0012", $destv->format("%04u"));

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

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

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

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

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

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

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

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

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

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

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

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

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

  function testNfloat() {
    /** @var ScalarValue $destv */
    Schema::nv($destv, $dest, null, $schema, "?float");
    $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());

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

    $destv->set(" ");
    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 testRequiredNfloat() {
    /** @var ScalarValue $destv */
    Schema::nv($destv, $dest, null, $schema, [
      "?float", 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());

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

    $destv->set(" ");
    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);
  }
}
