<?php

use Neomerx\JsonApi\Contracts\Schema\ContextInterface;
use Neomerx\JsonApi\Schema\BaseSchema;

class Account {

  public $id;

  // Attributes
  public $code;
  public $balance;
  public $creditLimit;
  public $maximumBalance;

  public $created;
  public $updated;

  // Relationships
  public $currency;
  public $settings;

  function __construct($account, Currency $currency) {
    // Identifier.
    $this->id = $account['uuid'];
    // Account number ABCD0123
    $this->code = $account['name'];
    // Balance
    $scale = $currency->scale;
    if (isset($account['balance']) && $account['balance'] !== null) {
      $this->balance = round(pow(10, $scale) * $account['balance']);
    } else {
      $this->balance = 0;
    }

    // Limits. We need to retrieve the info since it doesn't come with account record.
    $bank = new CesBank();
    $limitchain = $bank->getLimitChain($account['limitchain']);
    $creditLimit = - 1;
    $maximumBalance = -1;
    foreach($limitchain['limits'] as $limit) {
      if ($limit['block']) { // Don't take in count soft limits.
        if ($limit['classname'] == 'CesBankAbsoluteCreditLimit') {
          $maximumBalance = max($maximumBalance, $limit['value']);
        } else if ($limit['classname'] == 'CesBankAbsoluteDebitLimit') {
          $creditLimit = max($creditLimit, -$limit['value']);
        }
      }
    }
    $this->creditLimit = $creditLimit === -1 ? -1 : round($creditLimit * pow(10, $scale));
    $this->maximumBalance = $maximumBalance === -1 ? -1 : round($maximumBalance * pow(10, $scale));

    $this->created = SchemaUtils::encodeDate($account['created']);
    $this->updated = SchemaUtils::encodeDate($account['modified']);

    $this->currency = $currency;
    $this->settings = new AccountSettings($account, $currency);
  }
}
class AccountSchema extends BaseSchema {
  public function getType(): string {
    return 'accounts';
  }

  public function getId($account): ?string
  {
    assert($account instanceof Account);
    return (string) $account->id;
  }

  /**
   * @param Account $account
   */
  public function getAttributes($account, ContextInterface $context): iterable {
    assert($account instanceof Account);
    $attributes = [
      'code' => $account->code,
      'creditLimit' => $account->creditLimit,
      'maximumBalance' => $account->maximumBalance,
      'balance' => $account->balance,
      'created' => $account->created,
      'updated' => $account->updated,
    ];
    return $attributes;
  }

  public function getRelationships($account, ContextInterface $context): iterable
  {
    assert($account instanceof Account);
    return [
      'currency' =>  [
        self::RELATIONSHIP_DATA => $account->currency,
        self::RELATIONSHIP_LINKS_SELF => false,
        self::RELATIONSHIP_LINKS_RELATED => false
      ],
      'settings' => [
        self::RELATIONSHIP_DATA => $account->settings,
        self::RELATIONSHIP_LINKS_SELF => false,
        self::RELATIONSHIP_LINKS_RELATED => false
      ]
    ];
  }

  /**
   * @param mixed $resource
   *
   * @return string
   */
  protected function getSelfSubUrl($resource): string
  {
    return '/' . $resource->currency->code . $this->getResourcesSubUrl() . '/' . $resource->code;
  }

}
