// import Vue from "vue";
// const crypto = require("crypto");
import exportFromJSON from "export-from-json";
// import store from "@store/store";
export const isLoginRemoved = () => process.env.VUE_APP_LOGIN_REMOVE == 1;

// util to export to excel file using plugin
// https://github.com/zheeeng/export-from-json
// export const convertJsonToExcelUsingPlugin = async (
//   data,
//   fileName = "download"
// ) => {
//   // 'txt'(default), 'css', 'html', 'json', 'csv', 'xls', 'xml'
//   const exportType = exportFromJSON.types.xls;
//   const withBOM = true;

//   return await exportFromJSON({ data, fileName, exportType, withBOM });
// };

// util to export to excel file manually
export const exportJsonToExcelManually = (JSONData, FileTitle, ShowLabel) => {
  //If JSONData is not an object then JSON.parse will parse the JSON string in an Object
  var arrData = typeof JSONData != "object" ? JSON.parse(JSONData) : JSONData;
  var CSV = "";
  //This condition will generate the Label/Header
  if (ShowLabel) {
    var row = "";
    //This loop will extract the label from 1st index of on array
    for (var index in arrData[0]) {
      //Now convert each value to string and comma-seprated
      row += encodeURI(index) + ",";
    }
    row = row.slice(0, -1);
    //append Label row with line break
    CSV += row + "\r\n";
  }
  //1st loop is to extract each row
  for (var i = 0; i < arrData.length; i++) {
    var row = "";
    //2nd loop will extract each column and convert it in string comma-seprated
    for (var index in arrData[i]) {
      row += '"' + arrData[i][index] + '",';
    }
    row.slice(0, row.length - 1);
    //add a line break after each row
    CSV += row + "\r\n";
  }
  if (CSV == "") {
    alert("Invalid data");
    return;
  }
  //Generate a file name
  // application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8;
  // text/csv;charset=utf-8;
  // var csvContent = "data:text/csv;charset=utf-8,%EF%BB%BF" + encodeURI(csvContent);

  var filename = FileTitle;
  var blob = new Blob([CSV], {
    type: "text/csv;charset=utf-8,BOM",
  });

  if (navigator.msSaveBlob) {
    // IE 10+
    navigator.msSaveBlob(blob, filename);
  } else {
    var link = document.createElement("a");
    if (link.download !== undefined) {
      // feature detection
      // Browsers that support HTML5 download attribute
      var url = URL.createObjectURL(blob);
      link.setAttribute("href", url);
      link.style = "visibility:hidden";
      link.download = filename + ".csv";
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
    }
  }
};

// util to delay promise
export const wait = (ms) => {
  return (x) => {
    return new Promise((resolve) => setTimeout(() => resolve(x), ms));
  };
};
// util to createObjectByNewProperties
export const createObjectByNewProperties = (list, allowedProperties) => {
  const properties = [];

  list.forEach((item, index) => {
    const filtered = Object.keys(item)
      .filter((key) => allowedProperties.includes(key))
      .reduce((obj, key) => {
        obj[key] = item[key];
        return obj;
      }, {});

    properties[index] = filtered;
  });
  return properties;
};
// util to convert digits to character
export const toNumbersInCharacters = (number) => {
  const persianNumbers = ["۱", "۲", "۳", "۴", "۵", "۶", "۷", "۸", "۹", "۰"];
  const arabicNumbers = ["١", "٢", "٣", "٤", "٥", "٦", "٧", "٨", "٩", "٠"];
  const englishNumbers = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0"];
  const persianNumbersInCharacters = [
    "یک",
    "دو",
    "سه",
    "چهار",
    "پنج",
    "شش",
    "هفت",
    "هشت",
    "نه",
    "صفر",
  ];

  // only replace english number with persian number character
  return persianNumbersInCharacters[englishNumbers.indexOf(number)];

  // convert all numbers to persian digits
  // return str.split("").map(c =>
  //     persianNumbersInCharacters[englishNumbers.indexOf(c)] ||
  //     persianNumbersInCharacters[englishNumbers.indexOf(c)] || c).join("")
};
// util to handle if img src is not valid
export const handleImageSrcOnError = ({ target }, isUserAvatar = true) => {
  if (isUserAvatar) target.classList.add("human-avatar");
  target.classList.add("error");
};
// util to convert date to local date and time strng;
export const persianDateAndTime = (stringDate, local = "fa-IR") => {
  let date = new Date(stringDate);
  let jsonDate = {
    weekday: {
      long: date.toLocaleDateString(local, { weekday: "long" }),
      short: date.toLocaleDateString(local, { weekday: "short" }),
      narrow: date.toLocaleDateString(local, { weekday: "narrow" }),
    },
    era: {
      long: date.toLocaleDateString(local, { era: "long" }),
      short: date.toLocaleDateString(local, { era: "short" }),
      narrow: date.toLocaleDateString(local, { era: "narrow" }),
    },
    timeZoneName: {
      long: date.toLocaleDateString(local, { timeZoneName: "long" }),
      short: date.toLocaleDateString(local, { timeZoneName: "short" }),
    },
    year: {
      numeric: date.toLocaleDateString(local, { year: "numeric" }),
      "2-digit": date.toLocaleDateString(local, { year: "2-digit" }),
    },
    month: {
      numeric: date.toLocaleDateString(local, { month: "numeric" }),
      "2-digit": date.toLocaleDateString(local, { month: "2-digit" }),
      long: date.toLocaleDateString(local, { month: "long" }),
      short: date.toLocaleDateString(local, { month: "short" }),
      narrow: date.toLocaleDateString(local, { month: "narrow" }),
    },
    day: {
      numeric: date.toLocaleDateString(local, { day: "numeric" }),
      "2-digit": date.toLocaleDateString(local, { day: "2-digit" }),
    },
    hour: {
      numeric: date.toLocaleTimeString(local, { hour: "numeric" }),
      "2-digit": date.toLocaleTimeString(local, { hour: "2-digit" }),
    },
    minute: {
      numeric: date.toLocaleTimeString(local, { minute: "numeric" }),
      "2-digit": date.toLocaleTimeString(local, { minute: "2-digit" }),
    },
    second: {
      numeric: date.toLocaleTimeString(local, { second: "numeric" }),
      "2-digit": date.toLocaleTimeString(local, { second: "2-digit" }),
    },
  };
  return jsonDate;
};
// util to format numbers to local curency
export const formatNumber = (price = "") => {
  return new Intl.NumberFormat("fa-IR").format(price);
};

export const isValidHttpUrl = (string) => {
  let url;

  try {
    url = new URL(string);
  } catch (_) {
    return false;
  }

  return url.protocol === "http:" || url.protocol === "https:";
};
export const addJsCssFileToDom = (fileUrl, fileType, uuid) => {
  let targetElement =
    fileType == "js" ? "script" : fileType == "css" ? "link" : "none";
  let targetAttr =
    fileType == "js" ? "src" : fileType == "css" ? "href" : "none";

  let node = document.createElement(targetElement);
  node.setAttribute(targetAttr, fileUrl);
  node.setAttribute("id", targetElement + "-" + uuid);

  document.head.appendChild(node);
};
export const removeJsCssFileFromDom = (fileType, uuid) => {
  let targetElement =
    fileType == "js" ? "script" : fileType == "css" ? "link" : "none";
  document.getElementById(targetElement + "-" + uuid)?.remove();
};
export const clearBodyClass = (className = undefined) => {
  if (className) document.querySelector("html").replace(className, "");
  else document.querySelector("html").removeAttribute("class");
};
export const redirectToExternalLink = (href, openInNewTab) => {
  if (href) {
    if (isValidHttpUrl(href) && openInNewTab) window.open(href, "_blank");
    else if (isValidHttpUrl(href) && !openInNewTab) window.location.href = href;
    else if (!isValidHttpUrl(href) && openInNewTab) {
      if (href.includes("www.")) window.open("http://" + href, "_blank");
    } else if (!isValidHttpUrl(href) && !openInNewTab) {
      if (href.includes("www.")) window.location.href = "http://" + href;
    }
  }
};
export const extractAllQueryParams = (href) => {
  return new URLSearchParams(href);

  // return new Proxy(new URLSearchParams(href), {
  // get: (searchParams, prop) => searchParams.get(prop),
  // });
};
export const makeQueryParams = (url, searchParams) => {
  var query = new URLSearchParams();

  // (A) URL SEARCH PARAMS OBJECT TO QUICKLY BUILD QUERY STRING
  Object.keys(searchParams).forEach((key) =>
    query.append(key, searchParams[key])
  );

  // (B) CONVERT TO STRING, APPEND TO URL
  url += "?" + query.toString();
  return url;
};

// export const decryptData = (
//   data,
//   key = "fTjWnZr4u7x!A%D*G-KaNdRgUkXp3s6v",
//   method = "AES-256-CBC",
//   iv = "poaskq2234??@35."
// ) => {
//   let decipher = crypto.createDecipheriv(method, key, iv);
//   let decrypted = decipher.update(data, "base64", "utf8");
//   let dd = decrypted + decipher.final("utf8");
//   return JSON.parse(dd);
// };

// util to handle response errors

export const handleErrors = (error) => {
  return new Promise((resolve, reject) => {
    /* 
      401: The HTTP 401 Unauthorized response status code indicates that
       the client request has not been completed because it lacks
       valid authentication credentials for the requested resource.

      403: The HTTP 403 Forbidden response status code indicates that
      the server understands the request but refuses to authorize it.

      404:  The HTTP 404 Not Found response status code indicates that 
      the server cannot find the requested resource
      
      405: The HyperText Transfer Protocol (HTTP) 405 Method Not Allowed
       response status code indicates that the server knows the
      request method, but the target resource doesn't support this method

      406: Not Acceptable
      */
    try {
      let res = error.response;

      if (res) {
        if (res.status === 401) {
          toast.add({
            title: "خطا!",
            description: res.data.message,
          });

          //   router.push({ name: 'login' })
        } else if (res.status === 403) {
          toast.add({
            title: "خطا!",
            description: res.data.message,
          });
        } else if (res.status === 404) {
          toast.add({
            title: "خطا!",
            description: res.data.message,
          });

          // router.push('/404')
        } else if (res.status === 405) {
          toast.add({
            title: "خطا!",
            description: res.data.message,
          });

          // router.push('/404')
        } else if (res.status === 406) {
          toast.add({
            title: "خطا!",
            description: res.data.message,
          });

          // router.push('/404')
        } else if (res.status === 500) {
          toast.add({
            title: "خطا!",
            description: res.data.message ?? res.data,
          });
        } else {
          toast.add({
            title: "خطا!",
            description: res.data.message,
          });
        }

        resolve(error.response);
      } else {
        let message = "خطا!!!";

        // if (error) {
        //   message = error.message ?? error;
        // }
        // else
        // {
        //   message = "خطا!!!"
        // }

        reject(new Error(message));

        // text: error.stack,
        toast.add({
          title: message,
        });
      }
    } catch (error) {
      let message = "خطا!!!";
      message = error?.message ?? message;

      return reject(new Error(message));
    }
  });
};

function countDownTimer(timeInSecond = 120) {
  var timeleft = timeInSecond;
  var downloadTimer = setInterval(function () {
    if (timeleft <= 0) {
      clearInterval(downloadTimer);
      // document.getElementById("countdown").innerHTML = "Finished";
    } else {
      // document.getElementById("countdown").innerHTML =
      // timeleft + " seconds remaining";
    }
    timeleft -= 1;
  }, 1000);

  return timeleft;
}

///////////////////////////////////////
/////  html functions
///////////////////////////////////////
export function getSelectionHtmlRange() {
  var sel;
  if (window.getSelection) {
    sel = window.getSelection();
    if (sel.rangeCount) {
      return sel.getRangeAt(0);
    }
  } else if (document.selection) {
    return document.selection.createRange();
  }
  return null;
}

export function getSelectedHtmlInfo() {
  const selectRange = getSelectionHtmlRange();
  if (!selectRange) return {};

  // if (selectRange.startContainer !== selectRange.endContainer) {
  //   return;
  // }

  let begin = 0;
  let strBegin = "";
  let prevFullText = "";
  if (selectRange.startOffset > 0)
    strBegin = selectRange.startContainer.textContent.substring(
      0,
      selectRange.startOffset - 1
    );

  // برای وقتی که در تگ قبلی ، شماره کلمه انتها ذخیره شده است و نیازی به بررسی قبل از آن نیست
  if (
    selectRange.commonAncestorContainer.previousSibling &&
    selectRange.commonAncestorContainer.previousSibling.dataset?.end
  ) {
    begin =
      parseInt(
        selectRange.commonAncestorContainer.previousSibling.dataset.end
      ) + 1;
    begin += splitWord(strBegin).length;
  } else {
    prevFullText = getPreviousHtmlText(selectRange.startContainer, selectRange);
    begin += splitWord(prevFullText).length;
  }

  let selectedText = selectRange.startContainer.textContent.substring(
    selectRange.startOffset,
    selectRange.endOffset
  );
  let end = begin + splitWord(selectedText).length - 1;

  ///////////////////////////////////////////////////////
  ///// استخراج کلمه کلیک شده و دو کلمه بعدش
  ///// برای حالتی که متنی انتخاب نشده و فقط کلیک شده نیاز هست

  let node = selectRange.startContainer;
  const fullText = node.textContent;
  const offset = selectRange.startOffset;

  const words = fullText.split(/\s+/);
  let totalChars = 0;
  let wordIndex = -1;
  let wordsClicked = "";

  /// چون احتمال داره وسط کلمه کلیک شده باشه، قبل کلمه کلیک شده می ایستیم
  for (let i = 0; i < words.length; i++) {
    totalChars += words[i].length + 1;
    if (offset < totalChars) {
      wordIndex = i;
      break;
    }
  }

  if (wordIndex !== -1) {
    wordsClicked =
      words[wordIndex] +
      " " +
      (words[wordIndex + 1] || "") +
      " " +
      (words[wordIndex + 2] || "");
  }
  ///////////////////////////////////////////////////////

  let info = {
    begin: begin,
    end: end,
    selectedText: selectedText,
    prevTextBegin: strBegin,
    texts: wordsClicked,
    // prevTextFull: prevFullText,
  };
  return info;
}

export function getPreviousHtmlText(node, selectRange = null) {
  let text = "";
  if (!node) return text;
  else if (selectRange && node == selectRange.startContainer) {
    if (selectRange.startOffset > 0)
      text = selectRange.startContainer.textContent.substring(
        0,
        selectRange.startOffset - 1
      );
    // else
    //   text = selectRange.startContainer.textContent;
  } else text = node.textContent;

  if (node.previousSibling)
    text = getPreviousHtmlText(node.previousSibling, null) + text;

  return text;
}
////////////////////////////////////////////////////////////////////

export function splitWord(text) {
  let items = text.split(
    /[\t\n\r\.\'\"«»\)\(\]\[\{\}\%\#\$\*\<\>\/,;،؛ \-!?:٭؟]+/
  );
  // let items = text.split("\t\n\r.'\"«»)(][{}%#$*<>/,;،؛ -!?:٭؟")
  return items;
}

export function normalizeText(
  text,
  options = { charArNormal: true, errorLine: true }
) {
  // //defualt
  // options = {
  //   charArNormal: true,
  //   errorLine: true,
  //   alphabetsNormal: false,
  //   emptylinesNormal: false,
  //   hamzehNormal: false,
  //   spaceCorrection: false,
  //   trimLine: false
  // };

  text = text.trim();

  //اصلاح خطاهای متن در کد خط
  if (options?.errorLine) {
    text = text.replaceAll("\\n", "\n");
    text = text.replaceAll("\\r", "\r");
    text = replaceRegText("(\r\n)+", "\n", text);
    text = text.replaceAll("\r", "\n");

    //شنبهها ==> شنبه‌ها
    //رسیدگیهای ==> رسیدگی‌های
    // text = replaceRegText("(ه)(ها)", /\1\2/gm, text);
  }
  // یکسان سازی اختلاف حروف کیبوردهای مختلف - کدهای مختلف ولی نمایش یکسان
  if (options?.alphabetsNormal) {
    text = replaceAlphabets(text);
  }

  //حذف خطوط و فاصله‌های خالی
  if (options?.emptylinesNormal) {
    text = replaceRegText("( )+", " ", text);
    text = replaceRegText("(\n)+", "\n", text);
  }

  // نرمال کردن حروف اختلافی عربی و فارسی
  if (options?.charArNormal) {
    text = text.replaceAll("ي", "ی");
    text = text.replaceAll("ك", "ک");
  }

  // پرش از اختلافات همزه‌ای
  if (options?.hamzehNormal) {
    text = replaceRegText("ئ|ﺋ", "ی", text);
    text = replaceRegText("ؤ|ﺅ", "و", text);
    text = replaceRegText("ﺔ|ۀ|ة", "ه", text);
    text = replaceRegText("إ|أ", "ا", text);
  }
  if (options?.dateNormal) {
    text = dateNormalize(text);
  }
  if (options?.spaceCorrection) {
    text = spaceCorrection(text);
  }

  // حذف خطوط اضافی اول و انتهای متن
  if (options?.trimLine) text = text.replace(/^\s+|\s+$/g, "");

  text = text.trim();

  return text;
}

//برعکس بودن تاریخ ها را درست میکند
export function dateNormalize(text, forWord = false) {
  if (forWord) {
    // فرمت YYYY/MM/DD یا YYYY-MM-DD
    text = replaceRegText(
      /(\d{4})[\/\-](\d{1,2})[\/\-](\d{1,2})/,
      (_, year, month, day) =>
        `${day.padStart(2, "0")}/${month.padStart(2, "0")}/${year}`,
      text
    );

    // // فرمت DD/MM/YYYY یا DD-MM-YYYY
    // text = replaceRegText(
    //   /(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/,
    //   (_, day, month, year) =>
    //     `${year}/${month.padStart(2, "0")}/${day.padStart(2, "0")}`,
    //   text
    // );
  } else {
    // فرمت YYYY/MM/DD یا YYYY-MM-DD
    text = replaceRegText(
      /(\d{4})[\/\-](\d{1,2})[\/\-](\d{1,2})/,
      (_, year, month, day) =>
        `${year}/${month.padStart(2, "0")}/${day.padStart(2, "0")}`,
      text
    );

    // فرمت DD/MM/YYYY یا DD-MM-YYYY
    text = replaceRegText(
      /(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/,
      (_, day, month, year) =>
        `${year}/${month.padStart(2, "0")}/${day.padStart(2, "0")}`,
      text
    );
  }

  // // فرمت MM/DD/YYYY
  // text = replaceRegText(
  //   /(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/,
  //   (_, month, day, year) =>
  //     `${year}/${month.padStart(2, "0")}/${day.padStart(2, "0")}`,
  //   text
  // );
  return text;
}

export function replaceAlphabets(text) {
  let res = text;
  res = res.replaceAll("\u00AD", "\u200C");
  res = res.replaceAll("\u00AC", "\u200C"); // نیم اسپیس خاص

  res = replaceRegText("ﺁ|آ", "آ", res);
  res = replaceRegText("ﺎ|ٱ|ﺍ", "ا", res); //
  res = replaceRegText("ٲ|أ|ﺄ|ﺃ", "أ", res);
  res = replaceRegText("ﺈ|ﺇ", "إ", res);
  res = replaceRegText("ﺐ|ﺏ|ﺑ|ﺒ", "ب", res);
  res = replaceRegText("ﭖ|ﭗ|ﭙ|ﭘ", "پ", res);
  res = replaceRegText("ﭡ|ٺ|ٹ|ﭞ|ٿ|ټ|ﺕ|ﺗ|ﺖ|ﺘ", "ت", res);
  res = replaceRegText("ﺙ|ﺛ|ﺚ|ﺜ", "ث", res);
  res = replaceRegText("ﺝ|ڃ|ﺠ|ﺟ", "ج", res);
  res = replaceRegText("ڃ|ﭽ|ﭼ", "چ", res);
  res = replaceRegText("ﺢ|ﺤ|څ|ځ|ﺣ", "ح", res);
  res = replaceRegText("ﺥ|ﺦ|ﺨ|ﺧ", "خ", res);
  res = replaceRegText("ڏ|ډ|ﺪ|ﺩ", "د", res);
  res = replaceRegText("ﺫ|ﺬ|ذ", "ذ", res);
  res = replaceRegText("ڙ|ڗ|ڒ|ڑ|ڕ|ﺭ|ﺮ", "ر", res);
  res = replaceRegText("ﺰ|ﺯ", "ز", res);
  res = replaceRegText("ﮊ", "ژ", res);
  res = replaceRegText("ݭ|ݜ|ﺱ|ﺲ|ښ|ﺴ|ﺳ", "س", res);
  res = replaceRegText("ﺵ|ﺶ|ﺸ|ﺷ", "ش", res);
  res = replaceRegText("ﺺ|ﺼ|ﺻ|ﺹ", "ص", res); //
  res = replaceRegText("ﺽ|ﺾ|ﺿ|ﻀ", "ض", res);
  res = replaceRegText("ﻁ|ﻂ|ﻃ|ﻄ", "ط", res);
  res = replaceRegText("ﻆ|ﻇ|ﻈ", "ظ", res);
  res = replaceRegText("ڠ|ﻉ|ﻊ|ﻋ|ﻌ", "ع", res);
  res = replaceRegText("ﻎ|ۼ|ﻍ|ﻐ|ﻏ", "غ", res);
  res = replaceRegText("ﻒ|ﻑ|ﻔ|ﻓ", "ف", res);
  res = replaceRegText("ﻕ|ڤ|ﻖ|ﻗ|ﻘ", "ق", res);
  res = replaceRegText("ڭ|ﻚ|ﮎ|ﻜ|ﮏ|ګ|ﻛ|ﮑ|ﮐ|ڪ|ك", "ک", res);
  res = replaceRegText("ﮚ|ﮒ|ﮓ|ﮕ|ﮔ", "گ", res);
  res = replaceRegText("ﻝ|ﻞ|ﻠ|ڵ|ﻟ", "ل", res); //
  res = replaceRegText("ﻵ|ﻶ|ﻷ|ﻸ|ﻹ|ﻺ|ﻻ|ﻼ", "لا", res); //
  res = replaceRegText("ﻡ|ﻤ|ﻢ|ﻣ", "م", res);
  res = replaceRegText("ڼ|ﻦ|ﻥ|ﻨ|ﻧ", "ن", res);
  res = replaceRegText("ވ|ﯙ|ۈ|ۋ|ﺆ|ۊ|ۇ|ۏ|ۅ|ۉ|ﻭ|ﻮ|ؤ", "و", res);
  res = replaceRegText("ﻬ|ھ|ﻩ|ﻫ|ﻪ|ە|ہ", "ه", res);
  res = replaceRegText("ﭛ|ﻯ|ۍ|ﻰ|ﻱ|ﻲ|ں|ﻳ|ﻴ|ﯼ|ې|ﯽ|ﯾ|ﯿ|ێ|ے|ى|ي", "ی", res);
  res = replaceRegText("¬", "‌", res);
  res = replaceRegText("•|·|●|·|・|∙|｡|ⴰ", ".", res);
  res = replaceRegText(",|٬|٫|‚|،", "،", res);
  res = replaceRegText("ʕ", "؟", res);
  res = replaceRegText("۰|٠", "0", res);
  res = replaceRegText("۱|١", "1", res);
  res = replaceRegText("۲|٢", "2", res);
  res = replaceRegText("۳|٣", "3", res);
  res = replaceRegText("۴|٤", "4", res);
  res = replaceRegText("۵", "5", res);
  res = replaceRegText("۶|٦", "6", res);
  res = replaceRegText("۷|٧", "7", res);
  res = replaceRegText("۸|٨", "8", res);
  res = replaceRegText("۹|٩", "9", res);
  res = replaceRegText("²", "2", res);
  res = replaceRegText("|ِ|ُ|َ|ٍ|ٌ|ً|", "", res);
  // res = replaceRegText("ـ", "_", res);
  res = replaceRegText("ـ", "-", res); //

  // res = replaceRegText("([\u0600-\u06FF])ـ([\u0600-\u06FF])", "\1\2", res)  // حذف حروف کشیده
  // res = replaceRegText("([\u0600-\u06FF])ـ", "\1", res)  // حذف حروف کشیده

  res = res.replace(/\u200C+$/, "");
  res = res.trim();

  return res;
}

export function spaceCorrection(text) {
  let res = text;
  res = replaceRegText("^(بی|می|نمی)( )", "$1‌", res);
  res = replaceRegText("( )(می|نمی|بی)( )", "$1$2‌", res);
  res = replaceRegText(
    "( )(هایی|ها|های|ایی|هایم|هایت|هایش|هایمان|هایتان|هایشان|ات|ان|ین|انی|بان|ام|ای|یم|ید|اید|اند|بودم|بودی|بود|بودیم|بودید|بودند|ست)( )",
    "‌$2$3",
    res
  );
  res = replaceRegText("( )(شده|نشده)( )", "‌$2‌", res);
  res = replaceRegText(
    "( )(طلبان|طلب|گرایی|گرایان|شناس|شناسی|گذاری|گذار|گذاران|شناسان|گیری|پذیری|بندی|آوری|سازی|بندی|کننده|کنندگان|گیری|پرداز|پردازی|پردازان|آمیز|سنجی|ریزی|داری|دهنده|آمیز|پذیری|پذیر|پذیران|گر|ریز|ریزی|رسانی|یاب|یابی|گانه|گانه‌ای|انگاری|گا|بند|رسانی|دهندگان|دار)( )",
    "‌$2$3",
    res
  );
  return res;
}

export function replaceRegText(pattern, replacement, text) {
  const regex = new RegExp(pattern, "g");
  return text.replace(regex, replacement);
}

export function generateUID() {
  // I generate the UID from two parts here
  // to ensure the random number provide enough bits.
  var firstPart = (Math.random() * 46656) | 0;
  var secondPart = (Math.random() * 46656) | 0;
  firstPart = ("000" + firstPart.toString(36)).slice(-3);
  secondPart = ("000" + secondPart.toString(36)).slice(-3);
  return firstPart + secondPart; // eg : 9c8yxr
}

function myEncodeQuery(text) {
  if (!text || text == "") return "";
  //text = JSON.stringify(text);
  let ch1 = encodeURIComponent("#");
  let ch3 = encodeURIComponent("\\");
  let ch4 = encodeURIComponent("&");
  text = text.replaceAll("#", ch1);
  text = text.replaceAll("&", ch4);
  text = text.replaceAll("/", "\\");
  text = text.replaceAll("\\", ch3);

  // با تبدیل نقطه مشکل نشانی درخواست در بک حل نشد
  //text = text.replaceAll(".", '%2E');
  return text;
}

export function cleanTextUnpermittedChars(text) {
  if (!text) return "";

  text = text.replaceAll("([0x0000-0x001F]|(0x007F))", "");
  return text;
}


// utils/tree.js
export function findNodeWithPath(nodes, targetId, path = []) {
  for (let i = 0; i < nodes.length; i++) {
    const node = nodes[i];
    const currentPath = [...path, i];

    // ✅ Adjust this condition based on how you identify a node
    if (node.id === targetId) {
      return { node, path: currentPath };
    }

    // Recurse into children if they exist
    if (node.children && node.children.length > 0) {
      const result = findNodeWithPath(node.children, targetId, currentPath);
      if (result) return result;
    }
  }
  return null; // Not found
}

export function updateNodeByPath(nodes, path, newValue) {
  let current = nodes;
  // Navigate to the parent of the target node
  for (let i = 0; i < path.length - 1; i++) {
    current = current[path[i]].children;
  }
  // Update the target node
  const targetIndex = path[path.length - 1];
  current[targetIndex] = { ...current[targetIndex], ...newValue };
}

//////////////////////////////////////////

// export { wait, handleErrors }
