import { Resolver, Query, FieldResolver, Root, Args, Arg, Ctx, Directive } from 'type-graphql'
import { getRepository } from 'typeorm'
import { Domain, ListParam, convertListParams } from '@things-factory/shell'
import { RobotArm, RobotArmList, Pose, RobotArmStatus, Joints } from './robotarm-type'

import { ROBOTICS_OBJECT_TYPES } from '../../controllers/robotics-types'
import { ConnectionManager } from '@things-factory/integration-base'
import { RobotArmAPI } from '../../controllers/robot-arm-api'

const debug = require('debug')('aidoop:robotics:robotarm-query')

// extend type Query {
//   robotArms(filters: [Filter!], pagination: Pagination, sortings: [Sorting!]): RobotArmList
//   robotArmPose(name: String!): Pose
//   robotArmGetPose(name: String!): Pose
//   robotArmGetStatus(name: String!): RobotArmStatus
//   robotArmJoints(name: String!): Joints
//   robotArmGetJoints(name: String!): Joints
// }

@Resolver(RobotArm)
export class RobotArmQuery {
  @Query(returns => RobotArm, { description: 'To fetch a RobotArm' })
  async robotArm(
    @Arg('name', type => String, { nullable: false }) name: string,
    @Ctx() context: any
  ): Promise<RobotArm> {
    const { domain } = context.state

    var connection = ConnectionManager.getConnectionInstanceByName(domain, name)

    debug('connection', connection)

    if (!connection || connection.discriminator !== ROBOTICS_OBJECT_TYPES.ROBOT_ARM) {
      debug(`RobotArm '${name}' Not Found`)
      throw Error(`RobotArm '${name}' Not Found`)
    }

    var { markerOffset, toolOffset } = connection.params || {}

    debug('result', markerOffset, toolOffset)

    return {
      ...connection,
      markerOffset,
      toolOffset
    }
  }

  @Query(returns => RobotArmList, { description: 'To fetch multiple RobotArms' })
  async robotArms(@Args() params: ListParam, @Ctx() context: any): Promise<RobotArmList> {
    const { domain } = context.state

    var items = Object.keys(ConnectionManager.getConnectionInstances(domain))
      .map(name => ConnectionManager.getConnectionInstanceByName(domain, name))
      .filter(connection => connection.discriminator == ROBOTICS_OBJECT_TYPES.ROBOT_ARM)
      .map(connection => {
        var { markerOffset, toolOffset } = connection.params || {}

        return {
          ...connection,
          markerOffset,
          toolOffset
        }
      })

    return {
      items,
      total: items.length
    }
  }

  @Query(returns => Pose, { description: 'To fecth the current pose of the robot' })
  async robotArmPose(
    @Arg('name', type => String, { nullable: false }) name: string,
    @Ctx() context: any
  ): Promise<Pose> {
    const { domain } = context.state

    // @deprecated replaced by robotArmGetPose
    return RobotArmAPI.getPose(domain, name)
  }

  @Query(returns => Pose, { description: 'To fecth the current pose of the robot' })
  async robotArmGetPose(
    @Arg('name', type => String, { nullable: false }) name: string,
    @Ctx() context: any
  ): Promise<Pose> {
    const { domain } = context.state

    // @deprecated replaced by robotArmGetPose
    return RobotArmAPI.getPose(domain, name)
  }

  @Query(returns => RobotArmStatus, { description: 'To fecth the current status of the robot' })
  async robotArmGetStatus(
    @Arg('name', type => String, { nullable: false }) name: string,
    @Ctx() context: any
  ): Promise<RobotArmStatus> {
    const { domain } = context.state

    return RobotArmAPI.getStatus(domain, name)
  }

  @Query(returns => Joints, { description: 'To fecth the current status of the robot' })
  async robotArmJoints(
    @Arg('name', type => String, { nullable: false }) name: string,
    @Ctx() context: any
  ): Promise<Joints> {
    const { domain } = context.state

    // @deprecated replaced by robotArmGetPose
    return RobotArmAPI.getJoints(domain, name)
  }

  @Query(returns => Joints, { description: 'To fecth the current status of the robot' })
  async robotArmGetJoints(
    @Arg('name', type => String, { nullable: false }) name: string,
    @Ctx() context: any
  ): Promise<Joints> {
    const { domain } = context.state

    // @deprecated replaced by robotArmGetPose
    return RobotArmAPI.getJoints(domain, name)
  }
}
