import {
  Count,
  CountSchema,
  Filter,
  FilterExcludingWhere,
  repository,
  Where,
} from '@loopback/repository';
import {
  post,
  param,
  get,
  getModelSchemaRef,
  patch,
  put,
  del,
  requestBody,
  response,
} from '@loopback/rest';
import {<%= modelName %>} from '../models';
import {<%= repositoryName %>} from '../repositories';

export class <%= className %>Controller {
  constructor(
    @repository(<%= repositoryName %>)
    public <%= repositoryNameCamel %> : <%= repositoryName %>,
  ) {}

  @post('<%= httpPathName %>')
  @response(200, {
    description: '<%= modelName %> model instance',
    content: {'application/json': {schema: getModelSchemaRef(<%= modelName %>)}},
  })
  async create(
    @requestBody({
      content: {
        'application/json': {
          schema: getModelSchemaRef(<%= modelName %>, {
            title: 'New<%= modelName %>',
            <%if (idOmitted) {%>exclude: ['<%= id %>'],<% } %>
          }),
        },
      },
    })
    <%= modelVariableName %>: <% if (!idOmitted) { -%><%= modelName %><% } else { -%>Omit<<%= modelName %>, '<%= id %>'><% } -%>,
  ): Promise<<%= modelName %>> {
    return this.<%= repositoryNameCamel %>.create(<%= modelVariableName %>);
  }

  @get('<%= httpPathName %>/count')
  @response(200, {
    description: '<%= modelName %> model count',
    content: {'application/json': {schema: CountSchema}},
  })
  async count(
    @param.where(<%= modelName %>) where?: Where<<%= modelName %>>,
  ): Promise<Count> {
    return this.<%= repositoryNameCamel %>.count(where);
  }

  @get('<%= httpPathName %>')
  @response(200, {
    description: 'Array of <%= modelName %> model instances',
    content: {
      'application/json': {
        schema: {
          type: 'array',
          items: getModelSchemaRef(<%= modelName %>, {includeRelations: true}),
        },
      },
    },
  })
  async find(
    @param.filter(<%= modelName %>) filter?: Filter<<%= modelName %>>,
  ): Promise<<%= modelName %>[]> {
    return this.<%= repositoryNameCamel %>.find(filter);
  }

  @patch('<%= httpPathName %>')
  @response(200, {
    description: '<%= modelName %> PATCH success count',
    content: {'application/json': {schema: CountSchema}},
  })
  async updateAll(
    @requestBody({
      content: {
        'application/json': {
          schema: getModelSchemaRef(<%= modelName %>, {partial: true}),
        },
      },
    })
    <%= modelVariableName %>: <%= modelName %>,
    @param.where(<%= modelName %>) where?: Where<<%= modelName %>>,
  ): Promise<Count> {
    return this.<%= repositoryNameCamel %>.updateAll(<%= modelVariableName %>, where);
  }

  @get('<%= httpPathName %>/{id}')
  @response(200, {
    description: '<%= modelName %> model instance',
    content: {
      'application/json': {
        schema: getModelSchemaRef(<%= modelName %>, {includeRelations: true}),
      },
    },
  })
  async findById(
    @param.path.<%= idType %>('id') id: <%= idType %>,
    @param.filter(<%= modelName %>, {exclude: 'where'}) filter?: FilterExcludingWhere<<%= modelName %>>
  ): Promise<<%= modelName %>> {
    return this.<%= repositoryNameCamel %>.findById(id, filter);
  }

  @patch('<%= httpPathName %>/{id}')
  @response(204, {
    description: '<%= modelName %> PATCH success',
  })
  async updateById(
    @param.path.<%= idType %>('id') id: <%= idType %>,
    @requestBody({
      content: {
        'application/json': {
          schema: getModelSchemaRef(<%= modelName %>, {partial: true}),
        },
      },
    })
    <%= modelVariableName %>: <%= modelName %>,
  ): Promise<void> {
    await this.<%= repositoryNameCamel %>.updateById(id, <%= modelVariableName %>);
  }

  @put('<%= httpPathName %>/{id}')
  @response(204, {
    description: '<%= modelName %> PUT success',
  })
  async replaceById(
    @param.path.<%= idType %>('id') id: <%= idType %>,
    @requestBody() <%= modelVariableName %>: <%= modelName %>,
  ): Promise<void> {
    await this.<%= repositoryNameCamel %>.replaceById(id, <%= modelVariableName %>);
  }

  @del('<%= httpPathName %>/{id}')
  @response(204, {
    description: '<%= modelName %> DELETE success',
  })
  async deleteById(@param.path.<%= idType %>('id') id: <%= idType %>): Promise<void> {
    await this.<%= repositoryNameCamel %>.deleteById(id);
  }
}
