<?php
require_once dirname(__FILE__) . '/SchemaUtils.php';

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

class Group {
  public $id;

  // Attributes
  public $status;
  public $code;
  public $name;
  public $description;
  public $image;
  public $website;
  public $access;
  public $location;
  public $address;

  public $created;
  public $updated;

  // Relationships
  public $currency_id;
  public $contacts;
  public $categories;
  public $groupSettings;
  public $admins;

  public $membersCount;
  public $needsCount;
  public $offersCount;

  // Helper
  public $exchange;

  // Permissions
  public $allowAnonymousMemberList;
  public $userAccess;


  function __construct($exchange)
  {
    $this->exchange = $exchange;

    $this->id = ces_komunitin_api_social_get_uuid(ResourceTypes::GROUP, $exchange['id']);

    $statuses = [
      CesBankExchange::STATE_PENDING => 'pending',
      CesBankExchange::STATE_ACTIVE => 'active',
      CesBankExchange::STATE_DISABLED => 'disabled',
    ];
    $this->status = isset($statuses[$exchange['state']]) ? $statuses[$exchange['state']] : 'unknown';

    $this->code = $exchange['code'];
    $this->name = $exchange['name'];

    $this->website = $exchange['website'];
    $this->access = 'public';

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

    $this->description = $exchange['data']['description'] ?? '';

    if (!empty($exchange['data']['image'])) {
      $file = file_load($exchange['data']['image']);
      $this->image = file_create_url($file->uri);
    }
    else {
      $this->image = null;
    }

    $this->location = [
      'name' => $exchange['town'],
      'type' => 'Point',
      'coordinates' => [$exchange['lng'], $exchange['lat']]
    ];
    $this->address = [
      'addressLocality' => $exchange['town'],
      'addressCountry' => $exchange['country'],
      'addressRegion' => $exchange['region'],
    ];

    // Relationships.
    // Provide at least an email contact: this is the email of the exchange
    // admin user.
    $admin = user_load($exchange['admin']);
    $this->contacts = [new Contact($admin, Contact::TYPE_EMAIL, $admin->mail, $this->code)];

    $contacts = $exchange['data']['contacts'] ?? [];
    foreach ($contacts as $type => $value) {
      $this->contacts[] = new Contact($admin, $type, $value, $this->code);
    }

    // Load categories for this group.
    $categories = ces_komunitin_api_social_categories_load_collection($exchange, null, null);
    $this->categories = array_map(function($category) {
      return new Category($category, $this);
    }, $categories);

    $this->admins = [new User($admin, $this)];

    $this->currency_id = $exchange['uuid_currency'];
    $this->membersCount = ces_komunitin_api_social_members_count($exchange);
    $this->needsCount = ces_komunitin_api_social_needs_count($exchange);
    $this->offersCount = ces_komunitin_api_social_offers_count($exchange);

    $this->groupSettings = new GroupSettings($exchange);

    $this->allowAnonymousMemberList = !empty($exchange['data']['komunitin_allow_anonymous_member_list']);
    $this->userAccess = ces_bank_access('view', 'exchange details', $exchange['id']);
  }
}

class GroupSchema extends BaseSchema {

  public function getType(): string {
    return 'groups';
  }

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

  public function getAttributes($group, ContextInterface $context): iterable {
    assert($group instanceof Group);
    $attributes = [
      'code' => $group->code,
      'name' => $group->name,
      'status' => $group->status,
      'description' => $group->description,
      'image' => $group->image,
      'address' => $group->address,
      'website' => $group->website,
      'access' => $group->access,
      'location' => $group->location,
      'created' => $group->created,
      'updated' => $group->updated,
    ];
    return $attributes;
  }

  public function getRelationships($group, ContextInterface $context): iterable {
    assert($group instanceof Group);
    $currencyHref = ces_komunitin_api_get_accounting_api_url($group->exchange) . '/' . $group->code . '/currency';
    return [
      'currency' => [
        self::RELATIONSHIP_DATA => new ExternalCurrency($group->currency_id, 'currencies', $currencyHref),
        self::RELATIONSHIP_LINKS_SELF => false,
        // Override default related link
        self::RELATIONSHIP_LINKS => [
          LinkInterface::RELATED => new Link(false, $currencyHref, false)
        ]
      ],
      'contacts' => [
        self::RELATIONSHIP_DATA => $group->contacts,
        self::RELATIONSHIP_LINKS_SELF => false,
        self::RELATIONSHIP_LINKS_RELATED => false
      ],
      'members' => [
        self::RELATIONSHIP_LINKS_SELF => false,
        self::RELATIONSHIP_LINKS_RELATED => $group->userAccess || $group->allowAnonymousMemberList,
        self::RELATIONSHIP_META => ['count' => $group->membersCount]
      ],
      'categories' => [
        self::RELATIONSHIP_DATA => $group->userAccess ? $group->categories : null,
        self::RELATIONSHIP_LINKS_SELF => false,
        self::RELATIONSHIP_LINKS_RELATED => $group->userAccess,
        self::RELATIONSHIP_META => ['count' => count($group->categories)]
      ],
      'offers' => [
        self::RELATIONSHIP_LINKS_SELF => false,
        self::RELATIONSHIP_LINKS_RELATED => $group->userAccess,
        self::RELATIONSHIP_META => ['count' => $group->offersCount]
      ],
      'needs' => [
        self::RELATIONSHIP_LINKS_SELF => false,
        self::RELATIONSHIP_LINKS_RELATED => $group->userAccess,
        self::RELATIONSHIP_META => ['count' => $group->needsCount]
      ],
      'settings' => [
        self::RELATIONSHIP_DATA => $group->groupSettings,
        self::RELATIONSHIP_LINKS_SELF => false,
        self::RELATIONSHIP_LINKS_RELATED => false
      ],
      'admins' => [
        self::RELATIONSHIP_DATA => $group->admins,
        self::RELATIONSHIP_LINKS_SELF => false,
        self::RELATIONSHIP_LINKS_RELATED => false
      ]
    ];
  }
  /**
   * Override default self URL.
   */
  protected function getSelfSubUrl($resource): string {
    return '/' . $resource->code;
  }
}
