import { cloneDeep, set } from 'lodash';

import { ApplicationConfiguration } from '../types/index.js';
import { ScopedDataTree } from './refactor.js';
import { Extractor } from './types.js';
import { PropertyUpdate, updateNameInEntityMap } from './updates.js';

export async function renameInApplicationConfiguration({
  dsl,
  oldName,
  newName,
  dataTree,
  extractPairs,
  namespace
}: {
  dsl: ApplicationConfiguration['dsl'];
  oldName: string;
  newName: string;
  dataTree: ScopedDataTree;
  extractPairs: Extractor;
  namespace?: string;
}): Promise<ApplicationConfiguration['dsl'] | undefined> {
  const newDSL = cloneDeep(dsl);

  if (!newDSL) {
    return dsl;
  }

  let updates: PropertyUpdate[] = [];

  if (newDSL?.events?.eventMap) {
    const eventUpdates = await updateNameInEntityMap({
      entityMap: newDSL?.events,
      dataTree,
      newName,
      oldName,
      namespace,
      parentKey: 'events',
      extractPairs
    });
    updates = [...updates, ...eventUpdates];
  }

  if (newDSL?.timers?.timerMap) {
    const timerUpdates = await updateNameInEntityMap({
      entityMap: newDSL?.timers,
      dataTree,
      newName,
      oldName,
      namespace,
      parentKey: 'timers',
      extractPairs
    });
    updates = [...updates, ...timerUpdates];
  }

  if (newDSL?.stateVars?.stateVarMap) {
    const stateVarUpdates = await updateNameInEntityMap({
      entityMap: newDSL?.stateVars,
      dataTree,
      newName,
      oldName,
      namespace,
      parentKey: 'stateVars',
      extractPairs
    });
    updates = [...updates, ...stateVarUpdates];
  }

  updates.forEach((update) => set(newDSL, update.propertyName, update.propertyValue));

  return newDSL;
}
