<?php
namespace nur\data\types;

use nur\b\ValueException;
use nur\data\types\impl\CBcType;
use nur\data\types\impl\CSiType;
use nur\data\types\impl\CSniType;
use nur\data\types\impl\CSsType;
use nur\t\TestCase;

class CompositeTypeTest extends TestCase {
  function test1() {
    $schema = [
      "a" => ["string"],
      "b" => ["int", "composite" => true],
      "c" => ["string", "composite" => true],
      "" => [
        "ctypes" => [
          "bc" => CBcType::class,
        ],
      ],
    ];
    $md = new Metadata($schema);
    $bcType = $md->getType("bc");

    $item = null;
    $md->ensureSchema($item);
    self::assertSame(["a" => "", "b" => 0, "c" => ""], $item);

    $bc = $bcType->with("4 hello");
    self::assertSame(["b" => 4, "c" => "hello"], $bc);

    $item = ["a" => "first", "b" => 2, "c" => "third"];
    self::assertSame("2 third", $bcType->format($item));

    $item["b"] = "4";
    $item["c"] = "  hello  ";
    $bcType->verifix($item, $result);
    self::assertSame(["a" => "first", "b" => 4, "c" => "hello"], $item);
    self::assertSame("4 hello", $bcType->format($item));

    $item["b"] = "not a number";
    self::assertFalse($bcType->verifix($item, $result));
    self::assertFalse($result["cresults"]["b"]["valid"]);
    self::assertSame(["a" => "first", "b" => "not a number", "c" => "hello"], $item);
  }

  function test2() {
    $schema = [
      "x" => ["string"],
      "y" => ["int", "composite" => true],
      "z" => ["string", "composite" => true],
      "" => [
        "ctypes" => [
          "bc" => [CBcType::class, [
            "ckeys" => ["y", "z"]
          ]],
        ],
      ],
    ];
    $md = new Metadata($schema);
    $bcType = $md->getType("bc");

    $bc = $bcType->with("4 hello");
    self::assertSame(["y" => 4, "z" => "hello"], $bc);

    $item = [
      "x" => "hello",
      "y" => 42,
      "z" => "world",
    ];
    self::assertSame("42 world", $bcType->format($item));
  }

  function testConsume1() {
    $t = new CSiType();
    self::assertSame(["s" => "first", "i" => 15], $t->with("first-15"));
    self::assertSame(["s" => "first", "i" => 15], $t->with("first 15"));
    self::assertSame(["s" => "first", "i" => 15], $t->with("first - 15"));
    self::assertException(ValueException::class, function() use($t) {
      $t->with("abc-15");
    });

    self::assertSame(["s" => "first", "i" => null], $t->with("first"));
    self::assertSame(["s" => "first", "i" => null], $t->with("first-"));
  }

  function testConsume2() {
    $t = new CSsType();
    self::assertSame(["s1" => "aa", "s2" => "ayes"], $t->with("aaayes"));
    self::assertSame(["s1" => "bxx", "s2" => null], $t->with("bxx"));
    self::assertSame(["s1" => "bxxx", "s2" => null], $t->with("bxxx"));
    self::assertSame(["s1" => "bxxx", "s2" => "x"], $t->with("bxxxx"));
    self::assertSame(["s1" => "bxxx", "s2" => "xx"], $t->with("bxxxxx"));
  }
}
