import { Context, Parent, ResolveField, Resolver } from '@nestjs/graphql';
import { Person } from '../models/Person';
import { Client } from '../../client';
import { UUID } from '../../global/scalars/UUID';
import {EmailAddress} from '../../global/scalars/EmailAddress'
import {OrganizerService} from '../../organizer/organizer.service'
import {Organizer} from '../../organizer/models/Organizer'

@Resolver(() => Person)
export class PersonResolver {
  @ResolveField(() => UUID, { nullable: false })
  async _id(
    @Context('client') client: Client,
    @Parent() parent: Person
  ): Promise<UUID> {
    return parent._id as UUID;
  }

  @ResolveField(() => String, { nullable: false })
  async givenName(
    @Context('client') client: Client,
    @Parent() parent: Person
  ): Promise<string> {
    return parent.givenName;
  }

  @ResolveField(() => String, { nullable: false })
  async familyName(
    @Context('client') client: Client,
    @Parent() parent: Person
  ): Promise<string> {
    return parent.familyName;
  }

  @ResolveField(() => String, { nullable: true })
  async token(
    @Context('client') client: Client,
    @Parent() parent: Person
  ): Promise<string> {
    if (!client.isSelf(parent._id)) return null;
    return client.getToken();
  }

  @ResolveField(() => EmailAddress, { nullable: true })
  async email(
    @Context('client') client: Client,
    @Parent() parent: Person
  ): Promise<EmailAddress> {
    if (!client.isMaster() && !client.isSelf(parent._id)) return null;
    return parent.email;
  }

  @ResolveField(() => [UUID], { nullable: true })
  async _adminOf(
    @Context('client') client: Client,
    @Parent() parent: Person
  ): Promise<UUID[]> {
    if (!client.isMaster() && !client.isSelf(parent._id)) return null;

    const organizerService = new OrganizerService();

    const o = await organizerService.find({ _admins: client.getUser()._id });
    return o.map(e => e._id);
  }

  @ResolveField(() => [Organizer], { nullable: true })
  async adminOf(
    @Context('client') client: Client,
    @Parent() parent: Person
  ): Promise<Organizer[]> {
    if (!client.isMaster() && !client.isSelf(parent._id)) return null;

    const organizerService = new OrganizerService();

    return organizerService.find({ _admins: client.getUser()._id });
  }

  @ResolveField(() => [UUID], { nullable: true })
  async _organizerOf(
    @Context('client') client: Client,
    @Parent() parent: Person
  ): Promise<UUID[]> {
    if (!client.isMaster() && !client.isSelf(parent._id)) return null;

    const organizerService = new OrganizerService();

    const o = await organizerService.find({ $or: [{_organizers: client.getUser()._id}] });
    return o.map(e => e._id);
  }

  @ResolveField(() => [Organizer], { nullable: true })
  async organizerOf(
    @Context('client') client: Client,
    @Parent() parent: Person
  ): Promise<Organizer[]> {
    if (!client.isMaster() && !client.isSelf(parent._id)) return null;

    const organizerService = new OrganizerService();

    return await organizerService.find({ $or: [{_organizers: client.getUser()._id}] });
  }
}