/**
 * © Copyright Outburn Ltd. 2022-2024 All Rights Reserved
 *   Project name: FUME-COMMUNITY
 */

/* eslint-disable @typescript-eslint/restrict-plus-operands */

import _ from 'lodash';

import { getCache } from '../cache';
import { initCapOnce, replaceColonsWithBrackets } from '../stringFunctions';
import { returnPathWithoutX } from './returnPathWithoutX';

const dev = process.env.NODE_ENV === 'dev';

const lastNode = (path: string) => {
  const nodes = path.split('.');
  return nodes[nodes.length - 1];
};

// Generate all the options for the next node's path, based on the optional types (value[x])
const generateNodeIdOptions = (element: any) => {
  if (dev) console.log({ generateNodeIdOptions, element });
  const fshOptions: string[] = [];
  const elementId: string = returnPathWithoutX(element.id);
  const elementType = _.get(element, 'type');
  if (!elementType) {
    return [];
  } else if (elementType.length === 1) {
    fshOptions.push(elementId.split('.')[elementId.split('.').length - 1] + '[x]');
  }

  elementType.forEach(t => {
    fshOptions.push(elementId + initCapOnce(t.code));
  });
  if (dev) console.log('(generateNodeIdOptions)', { fshOptions });
  return fshOptions;
};

/**
 * This functions looks for the current path in the current sd snapshot's elements.
 * It implements several rules:
 * 1 - Exact match: nodeName = nodeName
 * 2 - A choice type element ([x]) that’s constrained to a single type: nodeName = nodeName[x] and count(type) = 1
 * 3 - A chosen type from a choice element: nodeNameDataType = nodeName[x] and DataType in initCap(type.code), Filter result’s element.type array for: initCap(code) = DataType
 * 4 - A specific type in a sliced choice element: nodeNameDataType = nodeName[x]:nodeNameDataType
 * 5 - A slice entry: nodeName[sliceName] = nodeName:sliceName
 **/
export const getCurrElement = (currTypeStructureDefinition, currPath, nodes, pathNodes, rootType) => {
  if (dev) console.log({ getCurrElement, 'currTypeStructureDefinition.id': currTypeStructureDefinition.id, currPath, nodes, pathNodes, rootType });
  const { elementDefinition } = getCache();
  const cachedElementDefinition = elementDefinition.get(rootType + '-' + currPath);
  if (dev) console.log({ '(getCurrElement) fetching from elementDefinition cache': rootType + '-' + currPath, found: !!cachedElementDefinition });
  if (cachedElementDefinition) {
    return cachedElementDefinition;
  } else {
    const elements = currTypeStructureDefinition.snapshot.element.filter(e => {
      return (
        (
          e.id === currTypeStructureDefinition?.type + '.' + currPath
        ) || (
          e.id === currTypeStructureDefinition?.type + '.' + currPath + '[x]' && e?.type.length === 1
        ) || (
          replaceColonsWithBrackets(e.id) === currTypeStructureDefinition?.type + '.' + currPath
        ) || (
          e.path.endsWith('[x]') &&
          e.id === e.path + ':' + currPath &&
          e.type.length === 1 &&
          currPath === lastNode(e.path).split('[x]')[0] + initCapOnce(e.type[0].code) &&
          currPath.split('.').length === e.id.split('.').length - 1
        )
      ) || (
        e.id.split('.').length === (pathNodes.length + 1) && (
          pathNodes[nodes - 1] === e.id.split('.').slice(1).join('.') ||
          generateNodeIdOptions(e).find(o => o === currPath) ||
          pathNodes[nodes - 1] === _.get(returnPathWithoutX(e.id.split('.').slice(1).join('.')).split('[x]:'), '1', false)
        )
      ) || generateNodeIdOptions(e).find((o: any) => o.split('.').slice(1).join('.') === currPath);
    });
    if (dev) console.log('(getCurrElement)', { elements });
    return elements[elements.length - 1];
  }
};
