# Source: executrix/colorizer.js

    /**
     * @file colorizer.js
     * @module colorizer
     * @description Contains all of the functions needed to manage, parse and control font styles and font colors.
     * @requires module:configurator
     * @requires module:data
     * @requires {@link https://www.npmjs.com/package/@haystacks/constants|@haystacks/constants}
     * @requires {@link https://www.npmjs.com/package/chalk|chalk}
     * @requires {@link https://www.npmjs.com/package/path|path}
     * @author Seth Hollingsead
     * @date 2021/10/15
     * @copyright Copyright © 2022-… by Seth Hollingsead. All rights reserved
     */

    // Internal imports
    import configurator from '../executrix/configurator.js';
    import D from '../structures/data.js';
    // External imports
    import hayConst from '@haystacks/constants';
    import chalk from 'chalk';
    import path from 'path';

    const {bas, clr, cfg, msg, sys, wrd} = hayConst;
    const baseFileName = path.basename(import.meta.url, path.extname(import.meta.url));
    // executrix.colorizer.
    // eslint-disable-next-line no-unused-vars
    const namespacePrefix = wrd.cexecutrix + bas.cDot + baseFileName + bas.cDot;

    /**
     * @function colorizeMessageSimple
     * @description Applies a color setting to an entire message, according to the inputs, background or foreground font color settings.
     * @param {string} message The message that should be formatted and returned according to the inputs, and controlled by the system configuration setting.
     * @param {array<integers>} colorArray The RGB color array that describes the color that should be applied to the message.
     * @param {boolean} isForeground A True or False to indicate if the color setting should be applied to the foreground or not.
     * If False, then apply to the background.
     * @return {string} The message with the color setting applied.
     * @author Seth Hollingsead
     * @date 2022/03/29
     */
    async function colorizeMessageSimple(message, colorArray, isForeground) {
      // let functionName = colorizeMessageSimple.name;
      // console.log(`BEGIN ${namespacePrefix}${functionName} function`);
      // console.log(`message is: ${message}`);
      // console.log(`colorArray is: ${JSON.stringify(colorArray)}`);
      // console.log(`isForeground is: ${isForeground}`);
      let colorizedMessage = message;
      let colorizeLogsEnabled = await configurator.getConfigurationSetting(wrd.csystem, cfg.cenableColorizedConsoleLogs);
      if (colorizeLogsEnabled === true) {
        let red = colorArray[0];
        let green = colorArray[1];
        let blue = colorArray[2];
        if (isForeground === true) {
          colorizedMessage = chalk.rgb(red,green,blue)(colorizedMessage);
        } else {
          colorizedMessage = chalk.bgRgb(red,green,blue)(colorizedMessage);
        }
      } // End-if (colorizeLogsEnabled === true)
      // console.log('colorizedMessage is: ' + colorizedMessage);
      // console.log(`END ${namespacePrefix}${functionName} function`);
      return colorizedMessage;
    }

    /**
     * @function colorizeMessage
     * @description Applies color settings to various portions of the message according to the settings from the configuration system.
     * @param {string} message The message that should be formatted and returned to be logged to the console and/or logged to a log file.
     * @param {string} className The name of the module/file that made the log call.
     * @param {string} functionName The name of the function that made the log call.
     * @param {boolean} debugFilesSetting A True or False value to indicate if the log should happen according to the file/module name.
     * Setting is set in the configuration/settings system.
     * @param {boolean} debugFunctionsSetting A True or False value to indicate if the log should happen according to the function/method name.
     * Setting is set in the configuration/settings system.
     * @param {boolean} flatMessageLog A True or False value to indicate if we are logging a flat message or if we should do additional processing.
     * We will probably do some additional processing either way, but there is a difference in the workflows.
     * For one a non-flat message will certainly have to replace a "%%" ith the class path (className,functionName),
     * and the associated formatting that goes with that according to the settings.
     * @return {string} A colorized version of the message.
     * @author Seth Hollingsead
     * @date 2022/01/28
     */
    async function colorizeMessage(message, className, callerFunctionName, debugFilesSetting, debugFunctionsSetting, flatMessageLog) {
      // let functionName = colorizeMessage.name;
      // console.log(`BEGIN ${namespacePrefix}${functionName} function`);
      // console.log(`message is: ${message}`);
      // console.log(`className is: ${className}`);
      // console.log(`callerFunctionName is: ${callerFunctionName}`);
      // console.log(`debugFilesSetting is: ${debugFilesSetting}`);
      // console.log(`debugFunctionsSetting is: ${debugFunctionsSetting}`);
      // console.log(`flatMessageLog is: ${flatMessageLog}`);
      let colorizedMessage;
      let messageContent;
      let messageContentPrefix;
      let messageContentSuffix;
      let messageData;
      let processingMessageData = false;
      let debugFilesModuleFontStyleSetting = wrd.cDefault;
      let debugFilesFunctionFontStyleSetting = wrd.cDefault;
      let debugFilesMessageFontStyleSetting = wrd.cDefault;
      let debugFilesDataFontStyleSetting = wrd.cDefault;
      let debugFilesModuleFontColorSetting = wrd.cDefault;
      let debugFilesFunctionFontColorSetting = wrd.cDefault;
      let debugFilesMessageFontColorSetting = wrd.cDefault;
      let debugFilesDataFontColorSetting = wrd.cDefault;
      let debugFilesModuleFontBackgroundColorSetting = wrd.cDefault;
      let debugFilesFunctionFontBackgroundColorSetting = wrd.cDefault;
      let debugFilesMessageFontBackgroundColorSetting = wrd.cDefault;
      let debugFilesDataFontBackgroundColorSetting = wrd.cDefault;

      let debugFunctionsModuleFontStyleSetting = wrd.cDefault;
      let debugFunctionsFunctionFontStyleSetting = wrd.cDefault;
      let debugFunctionsMessageFontStyleSetting = wrd.cDefault;
      let debugFunctionsDataFontStyleSetting = wrd.cDefault;
      let debugFunctionsModuleFontColorSetting = wrd.cDefault;
      let debugFunctionsFunctionFontColorSetting = wrd.cDefault;
      let debugFunctionsMessageFontColorSetting = wrd.cDefault;
      let debugFunctionsDataFontColorSetting = wrd.cDefault;
      let debugFunctionsModuleFontBackgroundColorSetting = wrd.cDefault;
      let debugFunctionsFunctionFontBackgroundColorSetting = wrd.cDefault;
      let debugFunctionsMessageFontBackgroundColorSetting = wrd.cDefault;
      let debugFunctionsDataFontBackgroundColorSetting = wrd.cDefault;

      // We need a 3rd set of variables because we wil need to aggregate these settings together to determine which ones are in effect.
      // One way is to aggregate each setting individually and let which ever one is defined be in effect.
      // Another way is to let the master debug functions and/or debug files setting be the controlling factor.
      // However, if both of them are set to true then we should default to determine which one is in effect from either one.
      // This will also let us do additional processing on the values that come from the settings file.
      // Because some of those settings like the colors and the font styles might have multiple sub-settings.
      // The color setting will of course have R,G,B; And the style setting might have Bold|Underline, so we will of curse have to parse those out.
      let aggregateModuleFontStyleUnderline = false;
      let aggregateModuleFontStyleBold = false;
      let aggregateFunctionFontStyleUnderline = false;
      let aggregateFunctionFontStyleBold = false;
      let aggregateMessageFontStyleUnderline = false;
      let aggregateMessageFontStyleBold = false;
      let aggregateDataFontStyleUnderline = false;
      let aggregateDataFontStyleBold = false;
      let aggregateModuleFontColorSetting = {};
      let aggregateFunctionFontColorSetting = {};
      let aggregateMessageFontColorSetting = {};
      let aggregateDataFontColorSetting = {};
      let aggregateModuleFontBackgroundColorSetting = {};
      let aggregateFunctionFontBackgroundColorSetting = {};
      let aggregateMessageFontBackgroundColorSetting = {};
      let aggregateDataFontBackgroundColorSetting = {};
      let aggregateUnderlineBoldArray = [];
      let messageBrokenDown = [];

      // debugFunctionsSetting = configurator.getConfigurationSetting(cfg.cdebugSetting + bas.cDot + configurationNamespace, configurationName);

      debugFilesModuleFontStyleSetting = await configurator.getConfigurationSetting(cfg.cdebugSetting + bas.cDot + className, bas.cAt + sys.cModuleFontStyle);
      // console.log('debugFilesModuleFontStyleSetting is: ' + debugFilesModuleFontStyleSetting);
      debugFilesFunctionFontStyleSetting = await configurator.getConfigurationSetting(cfg.cdebugSetting + bas.cDot + className, bas.cAt + sys.cFunctionFontStyle);
      // console.log('debugFilesFunctionFontStyleSetting is: ' + debugFilesFunctionFontStyleSetting);
      debugFilesMessageFontStyleSetting = await configurator.getConfigurationSetting(cfg.cdebugSetting + bas.cDot + className, bas.cAt + sys.cMessageFontStyle);
      // console.log('debugFilesMessageFontStyleSetting is: ' + debugFilesMessageFontStyleSetting);
      debugFilesDataFontStyleSetting = await configurator.getConfigurationSetting(cfg.cdebugSetting + bas.cDot + className, bas.cAt + sys.cDataFontStyle);
      // console.log('debugFilesDataFontStyleSetting is: ' + debugFilesDataFontStyleSetting);
      debugFilesModuleFontColorSetting = await configurator.getConfigurationSetting(cfg.cdebugSetting + bas.cDot + className, bas.cAt + sys.cModuleFontColor);
      // console.log('debugFilesModuleFontColorSetting is: ' + debugFilesModuleFontColorSetting);
      debugFilesFunctionFontColorSetting = await configurator.getConfigurationSetting(cfg.cdebugSetting + bas.cDot + className, bas.cAt + sys.cFunctionFontColor);
      // console.log('debugFilesFunctionFontColorSetting is: ' + debugFilesFunctionFontColorSetting);
      debugFilesMessageFontColorSetting = await configurator.getConfigurationSetting(cfg.cdebugSetting + bas.cDot + className, bas.cAt + sys.cMessageFontColor);
      // console.log('debugFilesMessageFontColorSetting is: ' + debugFilesMessageFontColorSetting);
      debugFilesDataFontColorSetting = await configurator.getConfigurationSetting(cfg.cdebugSetting + bas.cDot + className, bas.cAt + sys.cDataFontColor);
      // console.log('debugFilesDataFontColorSetting is: ' + debugFilesDataFontColorSetting);
      debugFilesModuleFontBackgroundColorSetting = await configurator.getConfigurationSetting(cfg.cdebugSetting + bas.cDot + className, bas.cAt + sys.cModuleFontBackgroundColor);
      // console.log('debugFilesModuleFontBackgroundColorSetting is: ' + debugFilesModuleFontBackgroundColorSetting);
      debugFilesFunctionFontBackgroundColorSetting = await configurator.getConfigurationSetting(cfg.cdebugSetting + bas.cDot + className, bas.cAt + sys.cFunctionFontBackgroundColor);
      // console.log('debugFilesFunctionFontBackgroundColorSetting is: ' + debugFilesFunctionFontBackgroundColorSetting);
      debugFilesMessageFontBackgroundColorSetting = await configurator.getConfigurationSetting(cfg.cdebugSetting + bas.cDot + className, bas.cAt + sys.cMessageFontBackgroundColor);
      // console.log('debugFilesMessageFontBackgroundColorSetting is: ' + debugFilesMessageFontBackgroundColorSetting);
      debugFilesDataFontBackgroundColorSetting = await configurator.getConfigurationSetting(cfg.cdebugSetting + bas.cDot + className, bas.cAt + sys.cDataFontBackgroundColor);
      // console.log('debugFilesDataFontBackgroundColorSetting is: ' + debugFilesDataFontBackgroundColorSetting);

      debugFunctionsModuleFontStyleSetting = await configurator.getConfigurationSetting(cfg.cdebugSetting + bas.cDot + className, callerFunctionName + bas.cAt + sys.cModuleFontStyle);
      // console.log('debugFunctionsModuleFontStyleSetting is: ' + debugFunctionsModuleFontStyleSetting);
      debugFunctionsFunctionFontStyleSetting = await configurator.getConfigurationSetting(cfg.cdebugSetting + bas.cDot + className, callerFunctionName + bas.cAt + sys.cFunctionFontStyle);
      // console.log('debugFunctionsFunctionFontStyleSetting is: ' + debugFunctionsFunctionFontStyleSetting);
      debugFunctionsMessageFontStyleSetting = await configurator.getConfigurationSetting(cfg.cdebugSetting + bas.cDot + className, callerFunctionName + bas.cAt + sys.cMessageFontStyle);
      // console.log('debugFunctionsMessageFontStyleSetting is: ' + debugFunctionsMessageFontStyleSetting);
      debugFunctionsDataFontStyleSetting = await configurator.getConfigurationSetting(cfg.cdebugSetting + bas.cDot + className, callerFunctionName + bas.cAt + sys.cDataFontStyle);
      // console.log('debugFunctionsDataFontStyleSetting is: ' + debugFunctionsDataFontStyleSetting);
      debugFunctionsModuleFontColorSetting = await configurator.getConfigurationSetting(cfg.cdebugSetting + bas.cDot + className, callerFunctionName + bas.cAt + sys.cModuleFontColor);
      // console.log('debugFunctionsModuleFontColorSetting is: ' + debugFunctionsModuleFontColorSetting);
      debugFunctionsFunctionFontColorSetting = await configurator.getConfigurationSetting(cfg.cdebugSetting + bas.cDot + className, callerFunctionName + bas.cAt + sys.cFunctionFontColor);
      // console.log('debugFunctionsFunctionFontColorSetting is: ' + debugFunctionsFunctionFontColorSetting);
      debugFunctionsMessageFontColorSetting = await configurator.getConfigurationSetting(cfg.cdebugSetting + bas.cDot + className, callerFunctionName + bas.cAt + sys.cMessageFontColor);
      // console.log('debugFunctionsMessageFontColorSetting is: ' + debugFunctionsMessageFontColorSetting);
      debugFunctionsDataFontColorSetting = await configurator.getConfigurationSetting(cfg.cdebugSetting + bas.cDot + className, callerFunctionName + bas.cAt + sys.cDataFontColor);
      // console.log('debugFunctionsDataFontColorSetting is: ' + debugFunctionsDataFontColorSetting);
      debugFunctionsModuleFontBackgroundColorSetting = await configurator.getConfigurationSetting(cfg.cdebugSetting + bas.cDot + className, callerFunctionName + bas.cAt + sys.cModuleFontBackgroundColor);
      // console.log('debugFunctionsModuleFontBackgroundColorSetting is: ' + debugFunctionsModuleFontBackgroundColorSetting);
      debugFunctionsFunctionFontBackgroundColorSetting = await configurator.getConfigurationSetting(cfg.cdebugSetting + bas.cDot + className, callerFunctionName + bas.cAt + sys.cFunctionFontBackgroundColor);
      // console.log('debugFunctionsFunctionFontBackgroundColorSetting is: ' + debugFunctionsFunctionFontBackgroundColorSetting);
      debugFunctionsMessageFontBackgroundColorSetting = await configurator.getConfigurationSetting(cfg.cdebugSetting + bas.cDot + className, callerFunctionName + bas.cAt + sys.cMessageFontBackgroundColor);
      // console.log('debugFunctionsMessageFontBackgroundColorSetting is: ' + debugFunctionsMessageFontBackgroundColorSetting);
      debugFunctionsDataFontBackgroundColorSetting = await configurator.getConfigurationSetting(cfg.cdebugSetting + bas.cDot + className, callerFunctionName + bas.cAt + sys.cDataFontBackgroundColor);
      // console.log('debugFunctionsDataFontBackgroundColorSetting is: ' + debugFunctionsDataFontBackgroundColorSetting);

      aggregateUnderlineBoldArray = await aggregateStyleSetting(debugFilesModuleFontStyleSetting, debugFunctionsModuleFontStyleSetting, true);
      aggregateModuleFontStyleUnderline = aggregateUnderlineBoldArray[0];
      aggregateModuleFontStyleBold = aggregateUnderlineBoldArray[1];

      aggregateUnderlineBoldArray = await aggregateStyleSetting(debugFilesFunctionFontStyleSetting, debugFunctionsFunctionFontStyleSetting, true);
      aggregateFunctionFontStyleUnderline = aggregateUnderlineBoldArray[0];
      aggregateFunctionFontStyleBold = aggregateUnderlineBoldArray[1];

      aggregateUnderlineBoldArray = await aggregateStyleSetting(debugFilesMessageFontStyleSetting, debugFunctionsMessageFontStyleSetting, true);
      aggregateMessageFontStyleUnderline = aggregateUnderlineBoldArray[0];
      aggregateMessageFontStyleBold = aggregateUnderlineBoldArray[1];

      aggregateUnderlineBoldArray = await aggregateStyleSetting(debugFilesDataFontStyleSetting, debugFunctionsDataFontStyleSetting, true);
      aggregateDataFontStyleUnderline = aggregateUnderlineBoldArray[0];
      aggregateDataFontStyleBold = aggregateUnderlineBoldArray[1];

      aggregateModuleFontColorSetting = await aggregateStyleSetting(debugFilesModuleFontColorSetting, debugFunctionsModuleFontColorSetting, [0, 255, 255], false);
      aggregateFunctionFontColorSetting = await aggregateStyleSetting(debugFilesFunctionFontColorSetting, debugFunctionsFunctionFontColorSetting, [0, 255, 255], false);
      aggregateMessageFontColorSetting = await aggregateStyleSetting(debugFilesMessageFontColorSetting, debugFunctionsMessageFontColorSetting, [0, 255, 255], false);
      aggregateDataFontColorSetting = await aggregateStyleSetting(debugFilesDataFontColorSetting, debugFunctionsDataFontColorSetting, [0, 255, 255], false);
      aggregateModuleFontBackgroundColorSetting = await aggregateStyleSetting(debugFilesModuleFontBackgroundColorSetting, debugFunctionsModuleFontBackgroundColorSetting, [0, 0, 0], false);
      aggregateFunctionFontBackgroundColorSetting = await aggregateStyleSetting(debugFilesFunctionFontBackgroundColorSetting, debugFunctionsFunctionFontBackgroundColorSetting, [0, 0, 0], false);
      aggregateMessageFontBackgroundColorSetting = await aggregateStyleSetting(debugFilesMessageFontBackgroundColorSetting, debugFunctionsMessageFontBackgroundColorSetting, [0, 0, 0], false);
      aggregateDataFontBackgroundColorSetting = await aggregateStyleSetting(debugFilesDataFontBackgroundColorSetting, debugFunctionsDataFontBackgroundColorSetting, [0, 0, 0], false);

      if (message.includes(bas.cColon) === true) {
        messageBrokenDown = message.split(/:(.+)/); // Use regular expression to split on the first instance of ":" ONLY!
        messageContent = messageBrokenDown[0];
        messageData = messageBrokenDown[1];
        processingMessageData = true;
      } else {
        messageContent = message;
        processingMessageData = false;
      }
      // "good_luck_buddy".split(/_(.+)/)[1]
      // @see https://stackoverflow.com/questions/4607745/split-string-only-on-first-instance-of-specified-character
      if (flatMessageLog === false) {
        // console.log('processing flatMessageLot === false');
        if (messageContent.includes(bas.cDoublePercent) === true) {
          messageContentPrefix = messageContent.split(bas.cSpace)[0];
          messageContentSuffix = messageContent.split(bas.cSpace)[2];
        } // End-if (messageContent.includes(bas.cDoublePercent) === true)

        className = await setUnderlineFontStyleOnMessageComponentAccordingToSetting(className, aggregateModuleFontStyleUnderline);
        className = await setBoldFontStyleOnMessageComponentAccordingToSetting(className, aggregateModuleFontStyleBold);
        // console.log('Done processing underline & bold settings: className is: ' + className);
        callerFunctionName = await setUnderlineFontStyleOnMessageComponentAccordingToSetting(callerFunctionName, aggregateFunctionFontStyleUnderline);
        callerFunctionName = await setBoldFontStyleOnMessageComponentAccordingToSetting(callerFunctionName, aggregateFunctionFontStyleBold);
        // console.log('Done processing underline & bold settings: callerFunctionName is: ' + callerFunctionName);

        if (messageContent.includes(bas.cDoublePercent) === true) {
          messageContent = await setUnderlineFontStyleOnMessageComponentAccordingToSetting(messageContent, aggregateMessageFontStyleUnderline);
          messageContentPrefix = await setBoldFontStyleOnMessageComponentAccordingToSetting(messageContentPrefix, aggregateMessageFontStyleBold);

          messageContentSuffix = await setUnderlineFontStyleOnMessageComponentAccordingToSetting(messageContentSuffix, aggregateMessageFontStyleUnderline);
          messageContentSuffix = await setBoldFontStyleOnMessageComponentAccordingToSetting(messageContentSuffix, aggregateMessageFontStyleBold);

          messageContentPrefix = await setFontForegroundColorOnMessageComponentAccordingToSetting(messageContentPrefix, aggregateMessageFontColorSetting);
          messageContentSuffix = await setFontForegroundColorOnMessageComponentAccordingToSetting(messageContentSuffix, aggregateMessageFontColorSetting);

          messageContentPrefix = await setFontBackgroundColorOnMessageComponentAccordingToSetting(messageContentPrefix, aggregateMessageFontBackgroundColorSetting);
          messageContentSuffix = await setFontBackgroundColorOnMessageComponentAccordingToSetting(messageContentSuffix, aggregateMessageFontBackgroundColorSetting);
        } else {
          messageContent = await setUnderlineFontStyleOnMessageComponentAccordingToSetting(messageContent, aggregateMessageFontStyleUnderline);
          messageContent = await setBoldFontStyleOnMessageComponentAccordingToSetting(messageContent, aggregateMessageFontStyleBold);
          // console.log('Done processing underline & bold settings: messageContent is: ' + messageContent);

          if (processingMessageData === true) {
            messageData = await setUnderlineFontStyleOnMessageComponentAccordingToSetting(messageData, aggregateDataFontStyleUnderline);
            messageData = await setBoldFontStyleOnMessageComponentAccordingToSetting(messageData, aggregateDataFontStyleBold);
          } // End-if (processingMessageData === true)

          messageContent = await setFontForegroundColorOnMessageComponentAccordingToSetting(messageContent, aggregateMessageFontColorSetting);
          // console.log('Done processing foreground color settings: messageContent is: ' + messageContent);

          messageContent = await setFontBackgroundColorOnMessageComponentAccordingToSetting(messageContent, aggregateMessageFontBackgroundColorSetting);
          // console.log('Done processing background color settings: messageContent is: ' + messageContent);
        }
        className = await setFontForegroundColorOnMessageComponentAccordingToSetting(className, aggregateModuleFontColorSetting);
        // console.log('Done processing foreground color settings: className is: ' + className);
        callerFunctionName = await setFontForegroundColorOnMessageComponentAccordingToSetting(callerFunctionName, aggregateFunctionFontColorSetting);
        // console.log('Done processing foreground color settings: callerFunctionName is: ' + callerFunctionName);

        className = await setFontBackgroundColorOnMessageComponentAccordingToSetting(className, aggregateModuleFontBackgroundColorSetting);
        // console.log('Done processing background color settings: className is: ' + className);
        callerFunctionName = await setFontBackgroundColorOnMessageComponentAccordingToSetting(callerFunctionName, aggregateFunctionFontBackgroundColorSetting);
        // console.log('Done processing background color settings: callerFunctionName is: ' + callerFunctionName);

        if (processingMessageData === true) {
          messageData = await setFontForegroundColorOnMessageComponentAccordingToSetting(messageData, aggregateDataFontColorSetting);
          messageData = await setFontBackgroundColorOnMessageComponentAccordingToSetting(messageData, aggregateDataFontBackgroundColorSetting);
        } // End-if (processingMessageData === true)

        if (messageContent.includes(bas.cDoublePercent) === true) {
          colorizedMessage = messageContentPrefix + bas.cSpace + className + bas.cDot + callerFunctionName + bas.cSpace + messageContentSuffix;
        } else if (messageData !== undefined) {
          colorizedMessage = messageContent + bas.cColon + messageData;
        } else {
          colorizedMessage = messageContent;
        }
      } else if (flatMessageLog === true) {
        messageContent = await setUnderlineFontStyleOnMessageComponentAccordingToSetting(messageContent, aggregateMessageFontStyleUnderline);
        messageContent = await setBoldFontStyleOnMessageComponentAccordingToSetting(messageContent, aggregateMessageFontStyleBold);
        if (processingMessageData === true) {
          // console.log('Attempting to format the message data component of the message: ' + messageData);
          messageData = await setUnderlineFontStyleOnMessageComponentAccordingToSetting(messageData, aggregateDataFontStyleUnderline);
          messageData = await setBoldFontStyleOnMessageComponentAccordingToSetting(messageData, aggregateDataFontStyleBold);
          messageData = await setFontForegroundColorOnMessageComponentAccordingToSetting(messageData, aggregateDataFontColorSetting);
          messageData = await setFontBackgroundColorOnMessageComponentAccordingToSetting(messageData, aggregateDataFontBackgroundColorSetting);
          // console.log('Done formatting all of the messageData: ' + messageData);
        }
        messageContent = await setFontForegroundColorOnMessageComponentAccordingToSetting(messageContent, aggregateMessageFontColorSetting);
        messageContent = await setFontBackgroundColorOnMessageComponentAccordingToSetting(callerFunctionName, aggregateMessageFontBackgroundColorSetting);
        colorizedMessage = messageContent + bas.cColon + messageData;
      } else { // Just return the message as we got it and make sure it gets out!
        colorizedMessage = message; // Don't apply any colorizing to the default. We are not likely to hit this case anyway!!
      }
      // console.log('colorizedMessage is: ' + colorizedMessage);
      // console.log(`END ${namespacePrefix}${functionName} function`);
      return colorizedMessage;
    }

    /**
     * @function aggregateStyleSetting
     * @description Compares the two input settings and determines which one of them is valuable or not valuable.
     * @param {string} settingValue1 The file level setting from the configuration file.
     * @param {string} settingValue2 The function level setting from the configuration file.
     * @param {array<integer>} defaultColorArray The default color value that should be used.
     * @param {boolean} processAsFontSetting A True or False value to indicate if we are processing True = font setting, False = color setting.
     * @return {array<boolean>} An array of booleans, [0] = underline setting True or False; [1] = bold setting True or False.
     * @author Seth Hollingsead
     * @date 2022/01/31
     */
    async function aggregateStyleSetting(settingValue1, settingValue2, defaultColorArray, processAsFontSetting) {
      // let functionName = aggregateStyleSetting.name;
      // console.log(`BEGIN ${namespacePrefix}${functionName} function`);
      // console.log(`settingValue1 is: ${settingValue1}`);
      // console.log(`settingValue2 is: ${settingValue2}`);
      // console.log(`processAsFontSetting is: ${processAsFontSetting}`);
      let styles = [];
      if ((settingValue1 !== wrd.cDefault || settingValue2 !== wrd.cDefault) && (settingValue1 !== undefined || settingValue2 !== undefined)) {
        if ((settingValue1 !== wrd.cDefault && settingValue2 === wrd.cDefault) || (settingValue1 !== undefined && settingValue2 === undefined)) {
          if (processAsFontSetting === true) {
            styles = await getFontStyleSettingsFromSetting(settingValue1);
          } else {
            styles = await getColorStyleSettingFromSetting(settingValue1, defaultColorArray);
          }
        } else if ((settingValue1 === wrd.cDefault && settingValue2 !== wrd.cDefault) || (settingValue1 === undefined && settingValue2 !== undefined)) {
          if (processAsFontSetting === true) {
            styles = await getFontStyleSettingsFromSetting(settingValue2);
          } else {
            styles = await getColorStyleSettingFromSetting(settingValue2, defaultColorArray);
          }
        } else { // They both must be NOT default, so we set the aggregate value to the function setting.
          if (processAsFontSetting === true) {
            styles = await getFontStyleSettingsFromSetting(settingValue2);
          } else {
            styles = await getColorStyleSettingFromSetting(settingValue2, defaultColorArray);
          }
        }
      } // End-if ((settingValue1 !== wrd.cDefault || settingValue2 !== wrd.cDefault) && (settingValue1 !== undefined || settingValue2 !== undefined))
      // console.log('styles is: ' + JSON.stringify(styles));
      // console.log(`END ${namespacePrefix}${functionName} function`);
      return styles;
    }

    /**
     * @function getFontStyleSettingsFromSetting
     * @description Parses the font setting to determine if values should be set for bold and/or underline.
     * @param {string} settingValue The setting value that should be parsed.
     * @return {array<boolean>} An array of booleans, [0] = underline setting True or False; [1] = bold setting True or False.
     * @author Seth Hollingsead
     * @date 2022/01/31
     */
    async function getFontStyleSettingsFromSetting(settingValue) {
      // let functionName = getFontStyleSettingsFromSetting.name;
      // console.log(`BEGIN ${namespacePrefix}${functionName} function`);
      // console.log(`settingValue is: ${settingValue}`);
      let fontStyles = [false, false];
      let aggregateUnderlineBoldArray = [];
      if (settingValue.includes(bas.cPipe) === true) {
        if (settingValue.includes(bas.cPipe) === true) {
          aggregateUnderlineBoldArray = settingValue.split(bas.cPipe);
          // console.log('aggregateUnderlineBoldArray is: ' + JSON.stringify(aggregateUnderlineBoldArray));
          // console.log('aggregateUnderlineBoldArray[0] is: ' + aggregateUnderlineBoldArray[0]);
          // console.log('aggregateUnderlineBoldArray[1] is: ' + aggregateUnderlineBoldArray[1]);
          if (aggregateUnderlineBoldArray[0] === wrd.cUnderline && aggregateUnderlineBoldArray[1] === wrd.cBold) {
            // aggregateModuleFontStyleUnderline = true;
            // aggregateModuleFontStyleBold = true;
            fontStyles = [true, true];
          } else if (aggregateUnderlineBoldArray[0] === wrd.cBold && aggregateUnderlineBoldArray[1] === wrd.cUnderline) {
            // aggregateModuleFontStyleUnderline = true;
            // aggregateModuleFontStyleBold = true;
            fontStyles = [true, true];
          } else if (aggregateUnderlineBoldArray[0] === wrd.cUnderline && aggregateUnderlineBoldArray[1] !== wrd.cBold) {
            // aggregateModuleFontStyleUnderline = true;
            fontStyles = [true, false];
          } else if (aggregateUnderlineBoldArray[0] === wrd.cBold && aggregateUnderlineBoldArray[1] !== wrd.cUnderline) {
            // aggregateModuleFontStyleBold = true;
            fontStyles = [false, true];
          } else {
            // ERROR: Did not find any matching style logic pattern!
            console.log(msg.cDidNotFindAnyMatchingStyleLogicPattern);
          }
        } else if (settingValue === wrd.cUnderline) {
          // aggregateModuleFontStyleUnderline = true;
          fontStyles = [true, false];
        } else if (settingValue === wrd.cBold) {
          // aggregateModuleFontStyleBold = true;
          fontStyles = [false, true];
        }
      } // End-if (settingValue.includes(bas.cPipe) === true)
      // console.log('fontStyles is: ' + JSON.stringify(fontStyles));
      // console.log(`END ${namespacePrefix}${functionName} function`);
      return fontStyles;
    }

    /**
     * @function getColorStyleSettingFromSetting
     * @description Parses the color setting to determine if the value should be parsed or loaded from the color data tables by unique color name.
     * @param {string} settingValue The setting value, which could be RGB as in R,G,B or it could be a string-name as in a unique color name.
     * @param {array<integer>} defaultColorArray The default color value that should be used.
     * @return {object} A JSON object with three integers that represent RGB values, labeled as "Red", "Green", "Blue".
     * @author Seth Hollingsead
     * @date 2022/01/31
     */
    async function getColorStyleSettingFromSetting(settingValue, defaultColorArray) {
      // let functionName = getColorStyleSettingFromSetting.name;
      // console.log(`BEGIN ${namespacePrefix}${functionName} function`);
      // console.log(`settingValue is: ${settingValue}`);
      let colorStyle = {Red: 0, Green: 0, Blue: 0};
      let aggregateColorArray = [];
      if (settingValue !== undefined) {
        if (settingValue.includes(bas.cComa) === true) {
          aggregateColorArray = settingValue.split(bas.cComa);
          colorStyle[clr.cRed] = aggregateColorArray[0];
          colorStyle[clr.cGreen] = aggregateColorArray[1];
          colorStyle[clr.cBlue] = aggregateColorArray[2];
        } else if (settingValue === wrd.cDefault) {
          colorStyle = false; // Do not apply any color settings of any kind!
        } else { // It must be a named color.
          colorStyle = await getNamedColorData(settingValue, defaultColorArray);
        }
      } else {
        colorStyle = false;
      }
      // console.log('colorStyle is: ' + JSON.stringify(colorStyle));
      // console.log(`END ${namespacePrefix}${functionName} function`);
      return colorStyle;
    }

    /**
     * @function getNamedColorData
     * @description Queries the D-data structure for the named color data.
     * All of this data should have been loaded from the Colors.csv file.
     * @param {string} colorName The name of the color who's RGB value we should look up from the color data structure.
     * @param {array<integer>} defaultColorArray The default color that should be used.
     * @return {array<integer>} An array of integers that represent RGB values.
     * @author Seth Hollingsead
     * @date 2022/01/31
     */
    async function getNamedColorData(colorName, defaultColorArray) {
      // let functionName = getNamedColorData.name;
      // console.log(`BEGIN ${namespacePrefix}${functionName} function`);
      // console.log(`colorName is: ${colorName}`);
      let returnColorData = defaultColorArray;
      if (D[wrd.ccolors] !== undefined) {
        if (D[wrd.ccolors][sys.cColorData] !== undefined) {
          if (D[wrd.ccolors][sys.cColorData][colorName] !== undefined) {
            returnColorData[clr.cRed] = D[wrd.ccolors][sys.cColorData][colorName][clr.cRed];
            returnColorData[clr.cGreen] = D[wrd.ccolors][sys.cColorData][colorName][clr.cGreen];
            returnColorData[clr.cBlue] = D[wrd.ccolors][sys.cColorData][colorName][clr.cBlue];
          } else {
            returnColorData = defaultColorArray;
          }
        } else {
          returnColorData = defaultColorArray;
        }
      } else {
        returnColorData = defaultColorArray;
      }
      // console.log('returnColorData is: ' + JSON.stringify(returnColorData));
      // console.log(`END ${namespacePrefix}${functionName} function`);
      return returnColorData;
    }

    /**
     * @function setUnderlineFontStyleOnMessageComponentAccordingToSetting
     * @description Examines the underline setting value and determines if the underline font setting should be applied to the message component or not.
     * @param {string} messageComponent The message to which the underline font setting should be applied if the setting value calls for it.
     * @param {boolean} underlineSettingValue A True or False value to indicate if the underline font setting should be applied or not applied.
     * @return {string} The same as the input string, except perhaps it might have an underline setting applied to it.
     * @author Seth Hollingsead
     * @date 2022/01/31
     */
    async function setUnderlineFontStyleOnMessageComponentAccordingToSetting(messageComponent, underlineSettingValue) {
      // let functionName = setUnderlineFontStyleOnMessageComponentAccordingToSetting.name;
      // console.log(`BEGIN ${namespacePrefix}${functionName} function`);
      // console.log(`messageComponent is: ${messageComponent}`);
      // console.log(`underlineSettingValue is: ${underlineSettingValue}`);
      let returnMessageComponent = messageComponent;
      if (underlineSettingValue === true) {
        let colorizeLogsEnabled = await configurator.getConfigurationSetting(wrd.csystem, cfg.cenableColorizedConsoleLogs);
        if (colorizeLogsEnabled === true) {
          returnMessageComponent.chalk.underline(returnMessageComponent);
        }
      } // End-if (underlineSettingValue === true)
      // console.log('returnMessageComponent is: ' + returnMessageComponent);
      // console.log(`END ${namespacePrefix}${functionName} function`);
      return returnMessageComponent;
    }

    /**
     * @function setBoldFontStyleOnMessageComponentAccordingToSetting
     * @description Examines the bold setting value and determines if the bold font setting should be applied to the message component or not.
     * @param {string} messageComponent The message to which the bold font setting should be applied if the setting value calls for it.
     * @param {boolean} boldSettingValue A True or False value to indicate if the bold font setting should be applied or not applied.
     * @return {string} The same as the input string, except perhaps it might have a bold setting applied to it.
     * @author Seth Hollingsead
     * @date 2022/01/31
     */
    async function setBoldFontStyleOnMessageComponentAccordingToSetting(messageComponent, boldSettingValue) {
      // let functionName = setBoldFontStyleOnMessageComponentAccordingToSetting.name;
      // console.log(`BEGIN ${namespacePrefix}${functionName} function`);
      // console.log(`messageComponent is: ${messageComponent}`);
      // console.log(`boldSettingValue is: ${boldSettingValue}`);
      let returnMessageComponent = messageComponent;
      if (boldSettingValue === true) {
        let colorizeLogsEnabled = await configurator.getConfigurationSetting(wrd.csystem, cfg.cenableColorizedConsoleLogs);
        if (colorizeLogsEnabled === true) {
          returnMessageComponent = chalk.bold(returnMessageComponent);
        }
      } // End-if (boldSettingValue === true)
      // console.log('returnMessageComponent is: ' + returnMessageComponent);
      // console.log(`END ${namespacePrefix}${functionName} function`);
      return returnMessageComponent;
    }

    /**
     * @function setFontForegroundColorOnMessageComponentAccordingToSetting
     * @description Examines the color setting to determine if it is False,
     * if not False then it is assumed to be an array of RGB values which are assigned to the message foreground component using chalk.
     * @param {string} messageComponent The message to which the foreground color setting should be applied if the color setting value != false.
     * @param {boolean|array<integer>} colorSettingValue A value of False or an array of integers for RGB values. False if no color should be applied.
     * @return {string} The same as the input string, except perhaps it might have a foreground color setting applied to it.
     * @author Seth Hollingsead
     * @date 2022/01/31
     */
    async function setFontForegroundColorOnMessageComponentAccordingToSetting(messageComponent, colorSettingValue) {
      // let functionName = setFontForegroundColorOnMessageComponentAccordingToSetting.name;
      // console.log(`BEGIN ${namespacePrefix}${functionName} function`);
      // console.log(`messageComponent is: ${messageComponent}`);
      // console.log(`colorSettingValue is: ${JSON.stringify(colorSettingValue)}`);
      let returnMessageComponent = messageComponent;
      if (colorSettingValue !== false && colorSettingValue !== undefined) {
        // console.log('Red color setting value is: ' + colorSettingValue[clr.cRed]);
        // console.log('Green color setting value is: ' + colorSettingValue[clr.cGreen]);
        // console.log('Blue color setting value is: ' + colorSettingValue[clr.cBlue]);
        // console.log('Before using chalk, returnMessageComponent is: ' + returnMessageComponent);
        if (colorSettingValue[clr.cRed] !== undefined && colorSettingValue[clr.cGreen] !== undefined && colorSettingValue[clr.cBlue] !== undefined) {
          let colorizeLogsEnabled = await configurator.getConfigurationSetting(wrd.csystem, cfg.cenableColorizedConsoleLogs);
          if (colorizeLogsEnabled === true) {
            returnMessageComponent = chalk.rgb(colorSettingValue[clr.cRed], colorSettingValue[clr.cGreen], colorSettingValue[clr.cBlue])(returnMessageComponent);
          }
        } // End-if (colorSettingValue[clr.cRed] !== undefined && colorSettingValue[clr.cGreen] !== undefined && colorSettingValue[clr.cBlue] !== undefined)
      } // End-if (colorSettingValue !== false && colorSettingValue !== undefined)
      // console.log('returnMessageComponent is: ' + returnMessageComponent);
      // console.log(`END ${namespacePrefix}${functionName} function`);
      return returnMessageComponent;
    }

    /**
     * @function setFontBackgroundColorOnMessageComponentAccordingToSetting
     * @description Examines the color setting to determine if it is False,
     * if not False then it is assumed to be an array of RGB values which are assigned to the message background using chalk.
     * @param {string} messageComponent The message to which the background color setting should be applied if the color setting value != false.
     * @param {boolean|array<integer>} colorSettingValue A value of False or an array of integers for RGB values. False if not color should be applied.
     * @return {string} The same as the input string, except perhaps it might have a background color setting applied to it.
     * @author Seth Hollingsead
     * @date 2022/01/31
     */
    async function setFontBackgroundColorOnMessageComponentAccordingToSetting(messageComponent, colorSettingValue) {
      // let functionName = setFontBackgroundColorOnMessageComponentAccordingToSetting.name;
      // console.log(`BEGIN ${namespacePrefix}${functionName} function`);
      // console.log(`messageComponent is: ${messageComponent}`);
      // console.log(`colorSettingValue is: ${JSON.stringify(colorSettingValue)}`);
      let returnMessageComponent = messageComponent;
      if (colorSettingValue !== false && colorSettingValue !== undefined) {
        // console.log('Red color setting value is: ' + colorSettingValue[clr.cRed]);
        // console.log('Green color setting value is: ' + colorSettingValue[clr.cGreen]);
        // console.log('Blue color setting value is: ' + colorSettingValue[clr.cBlue]);
        // console.log('Before using chalk, returnMessageComponent is: ' + returnMessageComponent);
        if (colorSettingValue[clr.cRed] !== undefined && colorSettingValue[clr.cGreen] !== undefined && colorSettingValue[clr.cBlue] !== undefined) {
          let colorizeLogsEnabled = await configurator.getConfigurationSetting(wrd.csystem, cfg.cenableColorizedConsoleLogs);
          if (colorizeLogsEnabled === true) {
            returnMessageComponent = chalk.bgRgb(colorSettingValue[clr.cRed], colorSettingValue[clr.cGreen], colorSettingValue[clr.cBlue])(returnMessageComponent);
          }
        } // End-if (colorSettingValue[clr.cRed] !== undefined && colorSettingValue[clr.cGreen] !== undefined && colorSettingValue[clr.cBlue] !== undefined)
      } // End-if (colorSettingValue !== false && colorSettingValue !== undefined)
      // console.log('returnMessageComponent is: ' + returnMessageComponent);
      // console.log(`END ${namespacePrefix}${functionName} function`);
      return returnMessageComponent;
    }

    /**
     * @function removeFontStyles
     * @description Removes all font styles and formatting from a string.
     * @param {string} message The string message that has formatting applied to it where the formatting should be removed:
     * Example: [48;2;255;255;255m[38;2;0;0;0mBEGIN main program loop[39m[49m
     * Return: BEGIN main program loop
     * @return {string} The string without all the extra formatting.
     * @author Seth Hollingsead
     * @date 2022/01/31
     * @reference: {@link https://stackoverflow.com/questions/25245716/remove-all-ansi-colors-styles-from-strings}
     */
    async function removeFontStyles(message) {
      // let functionName = removeFontStyles.name;
      // console.log(`BEGIN ${namespacePrefix}${functionName} function`);
      // console.log(`message is: ${message}`);
      let returnMessage = '';
      if (message) {
        // [48;2;255;255;255m[38;2;0;0;0mBEGIN main program loop[39m[49m
        returnMessage = message.replace(/\u001b[^m]*?m/g,'');
      } // End-if (message)
      // console.log('returnMessage is: ' + returnMessage);
      // console.log(`END ${namespacePrefix}${functionName} function`);
      return returnMessage;
    }

    export default {
      colorizeMessageSimple,
      colorizeMessage,
      aggregateStyleSetting,
      getFontStyleSettingsFromSetting,
      getColorStyleSettingFromSetting,
      getNamedColorData,
      setUnderlineFontStyleOnMessageComponentAccordingToSetting,
      setBoldFontStyleOnMessageComponentAccordingToSetting,
      setFontForegroundColorOnMessageComponentAccordingToSetting,
      setFontBackgroundColorOnMessageComponentAccordingToSetting,
      removeFontStyles
    };