/* eslint-disable id-blacklist */
import { UseGuards } from '@nestjs/common';
import { Args, Query, Resolver, ResolveField, Mutation, Parent, Subscription } from '@nestjs/graphql';
import { <%= entityClass %>Service } from '../../service/<%= entityFileName %>.service';
import { PaginationArgs } from './pagination-util';
import { Create<%= entityClass %>Args, Update<%= entityClass %>Args } from '../../service/graphql/<%= entityFileName %>.input-type';
import { <%= entityClass %>, Paginated<%= entityClass %> } from '../../service/graphql/<%= entityFileName %>.object-type';
import { PageRequest } from '../../domain/base/pagination.entity';
import { pageRequestToFindManyOptions } from './pagination-util';
import { PubSubService } from '../../service/graphql/pub-sub.service';
import { AuthGuard, RolesGuard } from '../../security';
import { transformField } from './field-resolver-util';

<%_
const pkTypeInterface = getPkType(databaseType) === 'Long' ? 'Number' : 'String';
const pkType = pkTypeInterface.toLowerCase();
_%>

@UseGuards(AuthGuard, RolesGuard)
@Resolver(() => <%= entityClass %>)
export class <%= entityClass %>Resolver {
constructor(private <%= asEntity(entityInstance) %>Service: <%= entityClass %>Service, private pubSub: PubSubService) {}

  @Query(() => Paginated<%= entityClass %>)
  async get<%= entityNamePlural %>(@Args() options: PaginationArgs): Promise<Paginated<%= entityClass %>> {
    const pageRequest: PageRequest = new PageRequest(options.page, options.size, options.sort);
    return this.<%= asEntity(entityInstance) %>Service.findAndCount(pageRequestToFindManyOptions(pageRequest))
        .then(([results, count]) => new Paginated<%= entityClass %>(results, count, true));
  }

  @Query(() => <%= entityClass %>)
  async get<%= entityClass %>(@Args('id') id: <%= pkType %>): Promise<<%= entityClass %>> {
    return this.<%= asEntity(entityInstance) %>Service.findById(id)
  }

  @Mutation(() => <%= entityClass %>)
  async create<%= entityClass %>(@Args('<%= entityInstance %>') <%= entityInstance %>: Create<%= entityClass %>Args): Promise<<%= entityClass %>> {
    return await this.<%= asEntity(entityInstance) %>Service.save(<%= entityInstance %>);
  }

  @Mutation(() => <%= entityClass %>)
  async update<%= entityClass %>(@Args('<%= entityInstance %>') <%= entityInstance %>: Update<%= entityClass %>Args): Promise<<%= entityClass %>> {
    return await this.<%= asEntity(entityInstance) %>Service.update(<%= entityInstance %>);
  }

  @Mutation(() => <%= pkTypeInterface %>)
  async delete<%= entityClass %>(@Args('id') id: <%= pkType %>): Promise<<%= pkType %>> {
    await this.<%= asEntity(entityInstance) %>Service.deleteById(id);
    return id;
  }

<%_
  function mapArg(a) {
    const resolvedArg = typeof a === 'string' && a.startsWith('@') && a.substr(1);
    return resolvedArg || a;
  }

  function getOptions(a) {
    return `{ nullable: ${!a.required } ${a.defaultValue ? (', defaultValue: ' + a.defaultValue) : ''} }`;
  }

  for (const field of gqlFields) {
_%>
  @ResolveField()
  <%= field.name %>(@Parent() <%= entityInstance %>: <%= entityClass %>, <%- field.args.map(a => `@Args('${a.name}', ${getOptions(a)}) ${a.name}${a.required ? '' : '?'}: ${a.type}`)%>) {
    return transformField(<%= entityInstance %>.<%= field.target.name %>, [<%- field.transform.map(t => `{ operation: '${t.operation}', args: [ ${t.args.map(a => mapArg(a)).join(',')} ] }`).join(',') %>]);
  }
<%_
  }
_%>

  @Subscription(() => <%= pkTypeInterface %>)
  <%= entityNamePlural.toLowerCase() %>Updated(): AsyncIterator<<%= pkTypeInterface %>> {
    return this.pubSub.asyncIterator('<%= entityNamePlural.toLowerCase() %>');
  }
}

