import { Done } from '../../../../../../../Class/Functional/Done'
import { Graph } from '../../../../../../../Class/Graph'
import { Semifunctional } from '../../../../../../../Class/Semifunctional'
import {
  shareLocalGraph,
  stopBroadcastSource,
} from '../../../../../../../process/share/local'
import { System } from '../../../../../../../system'
import { $$refGlobalObj } from '../../../../../../../types/interface/async/AsyncU'
import { Unlisten } from '../../../../../../../types/Unlisten'
import { ID_LOCAL_SHARE_GRAPH } from '../../../../../../_ids'

export interface I {
  opt: {}
  graph: Graph
}

export interface O {
  id: string
}

export default class LocalShareGraph extends Semifunctional<I, O> {
  __ = ['U']

  private _connected: boolean = false

  private _id: string

  private _terminate: Unlisten

  constructor(system: System) {
    super(
      {
        fi: ['opt', 'graph'],
        fo: ['id'],
        i: ['done'],
        o: [],
      },
      {
        input: {
          graph: {
            ref: true,
          },
        },
      },
      system,
      ID_LOCAL_SHARE_GRAPH
    )

    this.addListener('destroy', () => {
      if (this._connected) {
        this._disconnect()
      }
    })
  }

  private _disconnect = () => {
    if (this._connected) {
      stopBroadcastSource(this._id)
      this._terminate()
      this._connected = false
    }
  }

  f({ opt, graph }: I, done: Done<O>): void {
    const __global_id = graph.getGlobalId()

    const $graph = $$refGlobalObj(this.__system, __global_id, ['U', 'C', 'G'])

    const { id, terminate } = shareLocalGraph($graph)

    this._id = id
    this._terminate = terminate
    this._connected = true

    done({ id })
  }

  d() {
    this._disconnect()
    this._id = undefined
  }
}
