import { EventSubscriber, EntitySubscriberInterface, InsertEvent, UpdateEvent, EntityManager } from 'typeorm'

import { HistoryEntitySubscriber } from '@operato/typeorm-history'
import { pubsub, getRepository } from '@things-factory/shell'

import { Process } from './process'
import { ProcessHistory } from './process-history'
import { Analysis } from '../analysis/analysis'
import { StedGraphGenerator } from '../../controllers/sted-graph/sted-graph-generator'
import { transformGraphicModelToStedModel } from '../../controllers/transformer'

async function saveAnalysis(process: Partial<Process>, tx: EntityManager) {
  var analysis = {
    process: { id: process.id }
  } as Analysis

  const repository = tx.getRepository(Analysis)

  analysis = (await repository.findOneBy(analysis as any)) || analysis

  analysis.model = transformGraphicModelToStedModel(JSON.parse(process.model))
  analysis.dag = new StedGraphGenerator(analysis.model).run()

  try {
    repository.save(analysis)
  } catch (err) {
    console.error(err)
  }
}

@EventSubscriber()
export class ProcessSubscriber implements EntitySubscriberInterface<Process> {
  listenTo() {
    return Process
  }

  async afterInsert(event: InsertEvent<Process>): Promise<any> {
    const process = event.entity

    await saveAnalysis(process, event.manager)

    //   pubsub.publish('process', {
    //     process
    //   })
  }

  async afterUpdate(event: UpdateEvent<Process>): Promise<any> {
    var process = event.entity

    await saveAnalysis(process, event.manager)

    // process = await getRepository(Process).findOne({
    //   where: { domain: { id: process.domainId }, id: process.id },
    //   relations: ['group']
    // })

    // if (process.group) {
    //   pubsub.publish('process-group', {
    //     processGroup: process.group
    //   })
    // }

    // pubsub.publish('process', {
    //   process
    // })
  }
}

@EventSubscriber()
export class ProcessHistoryEntitySubscriber extends HistoryEntitySubscriber<Process, ProcessHistory> {
  public get entity() {
    return Process
  }

  public get historyEntity() {
    return ProcessHistory
  }

  public async afterInsert(event: InsertEvent<Process>): Promise<void> {
    if (event.entity.state == 'released') {
      super.afterInsert(event)
    }
  }

  public async afterUpdate(event: UpdateEvent<Process>): Promise<void> {
    if (event.entity.state == 'released') {
      super.afterUpdate(event)
    }
  }
}
