<?php
namespace ProVM\Money;

use ProVM\Common\Alias\Model;
use ProVM\Common\Factory\Model as ModelFactory;

/**
 * @property int $id
 * @property string $code
 * @property string $name
 */
class Currency extends Model {
  public static $_table = 'currencies';

  protected $values;
  public function values(): ?array {
    if ($this->values === null) {
      $this->values = $this->parentOf(Value::class, [Model::CHILD_KEY => 'currency_id']);
      if ($this->values) {
        usort($this->values, function($a, $b) {
          return $b->dateTime()->timestamp - $a->dateTime()->timestamp;
        });
      }
    }
    return $this->values;
  }
  protected $latest;
  public function latest(): ?Value {
    if ($this->latest === null) {
      $this->latest = $this->values()[0];
    }
    return $this->latest;
  }
  protected $sources;
  public function sources(): ?array {
    if ($this->sources === null) {
      $this->sources = $this->parentOf(Source::class, [Model::CHILD_KEY => 'currency_id']);
    }
    return $this->sources;
  }
  protected $aliases;
  public function aliases() {
    if ($this->aliases === null) {
      $this->aliases = $this->parentOf(Alias::class, [Model::CHILD_KEY => 'currency_id']);
    }
    return $this->aliases;
  }

  protected static $fields = ['code', 'name'];
  public static function add(ModelFactory $factory, $info) {
    $input = array_intersect_key((array) $info, array_combine(self::$fields, self::$fields));
    $currency = $factory->find(Currency::class)->where([['code', $input['code']]])->one();
    $created = false;
    $result = (object) compact('input', 'currency', 'created');
    if (!$currency) {
      $currency = $factory->create(Currency::class, $input);
      $created = $currency->save();
      $result->created = $created;
    }
    $result->currency = $currency->asArray();
    return $result;
  }
  protected function checkCode(string $code): bool {
    return ($this->find(Currency::class)->where([['code', $code]])->one()) ? true : false;
  }
  public function edit($info): bool {
    $data = array_intersect_key((array) $info, array_combine(self::$fields, self::$fields));
    $edited = false;
    foreach ($data as $field => $value) {
      if ($this->{$field} != $value) {
        if ($field == 'code' and $this->checkCode($value)) {
          throw \Exception('Currency code ' . $value . ' is already in the database.');
        }
        $this->{$field} = $value;
        $edited = true;
      }
    }
    if ($edited) {
      $edited = $this->save();
    }
    return $edited;
  }
  public function addAlias($info) {
    $arr = (array) $info;
    $arr['currency_id'] = (int) $this->id;
    $result = Alias::add($this->factory, $arr);
    return $result;
  }
  public function addValue($info) {
    $arr = (array) $info;
    $arr['currency_id'] = (int) $this->id;
    $result = Value::add($this->factory, $arr);
    return $result;
  }
  public function addSource($info) {
    $arr = (array) $info;
    $arr['currency_id'] = (int) $this->id;
    $result = Source::add($this->factory, $arr);
    return $result;
  }

  public static function find(ModelFactory $factory, string $query) {
    $query = '%' . $query . '%';
    $currency = $factory->find(Currency::class)->where([
      ['code', $query, 'like']
    ])->one();
    if ($currency !== false and $currency !== null) {
      return $currency;
    }
    $currency = $factory->find(Currency::class)->where([
      ['name', $query, 'like']
    ])->one();
    if ($currency !== false and $currency !== null) {
      return $currency;
    }
    $alias = $factory->find(Alias::class)->where([
      ['alias', $query, 'like']
    ])->one();
    if ($alias !== false and $alias !== null) {
      return $alias->currency();
    }
    return false;
  }
}
