import { Resolver, Query, FieldResolver, Root, Args, Arg, Ctx, Directive } from 'type-graphql'
import { ScalarObject } from '@things-factory/shell'
import { TrackingWorkspace, TrackingWorkspaceList } from './tracking-workspace-type'
import { ROBOTICS_OBJECT_TYPES } from '../../controllers/robotics-types'
import { ConnectionManager } from '@things-factory/integration-base'

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

// extend type Query {
//   trackingWorkspaces(filters: [Filter], pagination: Pagination, sortings: [Sorting]): TrackingWorkspaceList
//   trackingWorkspace(name: String!): TrackingWorkspace
// }

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

    var connection = ConnectionManager.getConnectionInstanceByName(domain, name)
    if (!connection || connection.discriminator !== ROBOTICS_OBJECT_TYPES.WORKSPACE) {
      throw Error(`TrackingWorkspace '${name}' Not Found`)
    }

    return connection
  }

  @Query(returns => TrackingWorkspaceList, { description: 'To fetch multiple tracking workspaces' })
  async trackingWorkspaces(@Ctx() context: any): Promise<TrackingWorkspaceList> {
    const { domain } = context.state

    var items = Object.keys(ConnectionManager.getConnectionInstances(domain))
      .map(name => ConnectionManager.getConnectionInstanceByName(domain, name))
      .filter(connection => connection.discriminator == ROBOTICS_OBJECT_TYPES.WORKSPACE)

    return {
      items,
      total: items.length
    }
  }

  @FieldResolver(type => Boolean)
  detectionMethod(@Root() trackingWorkspace: TrackingWorkspace): boolean {
    return trackingWorkspace.params?.detectionMethod
  }

  @FieldResolver(type => Boolean)
  checkVideoStream(@Root() trackingWorkspace: TrackingWorkspace): boolean {
    return trackingWorkspace.params?.checkVideoStream
  }

  @FieldResolver(type => ScalarObject)
  async trackingCameras(@Root() trackingWorkspace: TrackingWorkspace): Promise<Object> {
    const { domain } = trackingWorkspace

    return Object.keys(ConnectionManager.getConnectionInstances(domain))
      .map(name => ConnectionManager.getConnectionInstanceByName(domain, name))
      .filter(connection => connection.discriminator == ROBOTICS_OBJECT_TYPES.CAMERA)
      .map(connection => {
        var { handEyeConfig, handEyeMatrix, cameraCalibration, rois, camObjOffset, width, height } =
          connection.params || {}
        var { cameraMatrix, distortionCoefficient } = cameraCalibration || {}

        return {
          ...connection,
          cameraMatrix,
          distortionCoefficient,
          handEyeConfig,
          handEyeMatrix,
          rois,
          camObjOffset,
          width,
          height
        }
      })
  }

  @FieldResolver(type => ScalarObject)
  async trackableObjects(@Root() trackingWorkspace: TrackingWorkspace): Promise<Object> {
    const { domain } = trackingWorkspace

    return Object.keys(ConnectionManager.getConnectionInstances(domain))
      .map(name => ConnectionManager.getConnectionInstanceByName(domain, name))
      .filter(connection => connection.discriminator == ROBOTICS_OBJECT_TYPES.OBJECT)
      .map(connection => {
        var { poiOffset } = connection.params || {}

        return {
          ...connection,
          poiOffset
        }
      })
  }

  @FieldResolver(type => ScalarObject)
  async robotArms(@Root() trackingWorkspace: TrackingWorkspace): Promise<Object> {
    const { domain } = trackingWorkspace

    return 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
        }
      })
  }
}
