import forEach from "../lodash-es/forEach2.js";
import clone from "../lodash-es/clone2.js";
import compact from "../lodash-es/compact.js";
import flatten from "../lodash-es/flatten2.js";
import map from "../lodash-es/map2.js";
import difference from "../lodash-es/difference.js";
import isEmpty from "../lodash-es/isEmpty2.js";
import isArray from "../lodash-es/isArray2.js";
import has from "../lodash-es/has2.js";
import includes from "../lodash-es/includes.js";
function tokenStructuredMatcher(tokInstance, tokConstructor) {
  const instanceType = tokInstance.tokenTypeIdx;
  if (instanceType === tokConstructor.tokenTypeIdx) {
    return true;
  } else {
    return tokConstructor.isParent === true && tokConstructor.categoryMatchesMap[instanceType] === true;
  }
}
function tokenStructuredMatcherNoCategories(token, tokType) {
  return token.tokenTypeIdx === tokType.tokenTypeIdx;
}
let tokenShortNameIdx = 1;
const tokenIdxToClass = {};
function augmentTokenTypes(tokenTypes) {
  const tokenTypesAndParents = expandCategories(tokenTypes);
  assignTokenDefaultProps(tokenTypesAndParents);
  assignCategoriesMapProp(tokenTypesAndParents);
  assignCategoriesTokensProp(tokenTypesAndParents);
  forEach(tokenTypesAndParents, (tokType) => {
    tokType.isParent = tokType.categoryMatches.length > 0;
  });
}
function expandCategories(tokenTypes) {
  let result = clone(tokenTypes);
  let categories = tokenTypes;
  let searching = true;
  while (searching) {
    categories = compact(flatten(map(categories, (currTokType) => currTokType.CATEGORIES)));
    const newCategories = difference(categories, result);
    result = result.concat(newCategories);
    if (isEmpty(newCategories)) {
      searching = false;
    } else {
      categories = newCategories;
    }
  }
  return result;
}
function assignTokenDefaultProps(tokenTypes) {
  forEach(tokenTypes, (currTokType) => {
    if (!hasShortKeyProperty(currTokType)) {
      tokenIdxToClass[tokenShortNameIdx] = currTokType;
      currTokType.tokenTypeIdx = tokenShortNameIdx++;
    }
    if (hasCategoriesProperty(currTokType) && !isArray(currTokType.CATEGORIES)) {
      currTokType.CATEGORIES = [currTokType.CATEGORIES];
    }
    if (!hasCategoriesProperty(currTokType)) {
      currTokType.CATEGORIES = [];
    }
    if (!hasExtendingTokensTypesProperty(currTokType)) {
      currTokType.categoryMatches = [];
    }
    if (!hasExtendingTokensTypesMapProperty(currTokType)) {
      currTokType.categoryMatchesMap = {};
    }
  });
}
function assignCategoriesTokensProp(tokenTypes) {
  forEach(tokenTypes, (currTokType) => {
    currTokType.categoryMatches = [];
    forEach(currTokType.categoryMatchesMap, (val, key) => {
      currTokType.categoryMatches.push(tokenIdxToClass[key].tokenTypeIdx);
    });
  });
}
function assignCategoriesMapProp(tokenTypes) {
  forEach(tokenTypes, (currTokType) => {
    singleAssignCategoriesToksMap([], currTokType);
  });
}
function singleAssignCategoriesToksMap(path, nextNode) {
  forEach(path, (pathNode) => {
    nextNode.categoryMatchesMap[pathNode.tokenTypeIdx] = true;
  });
  forEach(nextNode.CATEGORIES, (nextCategory) => {
    const newPath = path.concat(nextNode);
    if (!includes(newPath, nextCategory)) {
      singleAssignCategoriesToksMap(newPath, nextCategory);
    }
  });
}
function hasShortKeyProperty(tokType) {
  return has(tokType, "tokenTypeIdx");
}
function hasCategoriesProperty(tokType) {
  return has(tokType, "CATEGORIES");
}
function hasExtendingTokensTypesProperty(tokType) {
  return has(tokType, "categoryMatches");
}
function hasExtendingTokensTypesMapProperty(tokType) {
  return has(tokType, "categoryMatchesMap");
}
function isTokenType(tokType) {
  return has(tokType, "tokenTypeIdx");
}
export {
  assignCategoriesMapProp,
  assignCategoriesTokensProp,
  assignTokenDefaultProps,
  augmentTokenTypes,
  expandCategories,
  hasCategoriesProperty,
  hasExtendingTokensTypesMapProperty,
  hasExtendingTokensTypesProperty,
  hasShortKeyProperty,
  isTokenType,
  singleAssignCategoriesToksMap,
  tokenIdxToClass,
  tokenShortNameIdx,
  tokenStructuredMatcher,
  tokenStructuredMatcherNoCategories
};
//# sourceMappingURL=lib-src-scan-tokens.js.map
