<?php
namespace nur\data\types;

use nur\b\date\Time;

class TimeType extends AbstractSimpleType {
  const TITLE = "heure du jour";

  function getClass(): string {
    return Time::class;
  }

  function isInstance($value, bool $strict=false): bool {
    return $value === null || $value instanceof Time;
  }

  const TIME_PATTERN = '/^(\d+)\s*(?:[hH:.]\s*(?:(\d+)\s*(?:[:.]\s*(\d+)\s*)?)?)?/';

  /** @return array|false un tableau de la forme [$h, $m, $s] */
  function parse(string &$input) {
    if (preg_match(self::TIME_PATTERN, $input, $ms)) {
      $h = intval($ms[1]);
      $m = isset($ms[2])? intval($ms[2]): 0;
      $s = isset($ms[3])? intval($ms[3]): 0;
      $input = substr($input, strlen($ms[0]));
      return [$h, $m, $s];
    } else {
      return false;
    }
  }

  const ALLOW_NULL = true;
  const ALLOW_FALSE = false;

  function verifixReplaceNull(&$value): void {
    if (!$this->ppAllowNull) $value = Time::null();
  }

  function verifixReplaceFalse(&$value): void {
    if (!$this->ppAllowFalse) $value = Time::undef();
  }

  function verifixReplaceEmpty(&$value): void {
    if (!$this->ppAllowFalse) $value = Time::undef();
    else $value = false;
  }

  function verifixConvert(&$value): bool {
    if ($value === null) return true;
    $value = new Time($value[0] * 3600 + $value[1] * 60 + $value[2]);
    return true;
  }

  function dump($value) {
    if ($value instanceof Time) {
      if (!$this->ppAllowNull && $value->isNull()) $value = null;
      if (!$this->ppAllowFalse && $value->isUndef()) $value = false;
    }
    return $value;
  }

  function load($value) {
    if ($value === null && !$this->ppAllowNull) $value = Time::null();
    elseif ($value === false && !$this->ppAllowFalse) $value = Time::undef();
    return $value;
  }
  
  #############################################################################
  # Méthodes utilitaires
  
  function isNone($time): bool {
    if ($time instanceof Time) return $time->isNull();
    else return $time === null;
  }

  function isUndef($time, $key=null): bool {
    if ($key !== null) {
      if (!is_array($time)) return $key !== 0;
      if (!array_key_exists($key, $time)) return true;
      $time = $time[$key];
    }
    if ($time instanceof Time) return $time->isUndef();
    else return $time === false;
  }

  function add($time, $add): ?Time {
    $time = $this->with($time);
    $add = $this->with($add);
    if ($add === null) return $time;
    elseif ($time === null) return $add;
    return $time->add($add);
  }

  function sub($time, $sub): ?Time {
    $time = $this->with($time);
    $sub = $this->with($sub);
    if ($sub === null) return $time;
    elseif ($time === null) $time = $sub->newu(0);
    return $time->sub($sub);
  }

  function cmp($time, $other): int {
    $time = $this->with($time);
    $other = $this->with($other);
    if ($time === null && $other === null) return 0;
    elseif ($time === null) return -1;
    elseif ($other === null) return 1;
    return $time->cmp($other);
  }

  function before($time, $other): bool {
    $time = $this->with($time);
    $other = $this->with($other);
    if ($time === null && $other === null) return true;
    elseif ($time === null) return true;
    elseif ($other === null) return false;
    return $time->before($other);
  }

  function after($time, $other): bool {
    $time = $this->with($time);
    $other = $this->with($other);
    if ($time === null && $other === null) return true;
    elseif ($time === null) return false;
    elseif ($other === null) return true;
    return $time->after($other);
  }
}
