'use strict'
import consul from 'consul'
import { exec } from './src/io/run.mjs'
import { readFile } from './src/io/files.mjs'

import ctlg_control_loop from './src/catalog/control_loop.mjs'
import ctlg_consul from './src/catalog/consul.mjs'
import inj_iptables from './src/injector/iptables.mjs'

const get_args = () => process
  .argv
  .slice(2)
  .map(a => a.split('='))
  .reduce((dict, tuple) => {
    dict[tuple[0]] = tuple.length > 1 ? tuple[1] : null
    return dict
  }, {})

/**
 * If we have multiple catalogs
 * we cache the results of the other ones
 */
function* notifications_aggregator(injectors) {
  const states = []
  for(let idx = 0; true; idx++) {
    yield async (tag_list) => {
      states[idx] = tag_list
      const merged = states.reduce((acc, tag) => [...acc, ...tag], [])
      await Promise.all(injectors.map(notify => notify(merged)))
    }
  }
}

const main = async () => {
  try {
    const args = get_args()

    // Initialize all injectors
    const injectors = [
      await inj_iptables(args.ipt_base, readFile, exec, console.log),
      // await inj_upnp
    ]
    
    // Initialize all catalogs and map them to the injectors
    const aggr = notifications_aggregator(injectors)
    const catalogs = [
      // this catalog is used to defeat deriving config due to single resource updated async. by multiple prog or by external program not tracked by catalogs
      await ctlg_control_loop(setInterval, 60000, aggr.next().value),       
      await ctlg_consul(args.node, consul(), console.log, aggr.next().value)
    ]

    console.log("[main] initialized")
  } catch(e) {
    console.error("initialization failed", e)
    process.exit(1)
  }
}

main()
