"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  // If the importer is in node compatibility mode or this is not an ESM
  // file that has been converted to a CommonJS file using a Babel-
  // compatible transform (i.e. "__esModule" has not been set), then set
  // "default" to the CommonJS "module.exports" for node compatibility.
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);

// src/common/utils.ts
var utils_exports = {};
__export(utils_exports, {
  ERROR_CODE_NOT_IMPLEMENTED_AS_DESIGNED: () => ERROR_CODE_NOT_IMPLEMENTED_AS_DESIGNED,
  forceClosePopup: () => forceClosePopup,
  generateCacheId: () => generateCacheId,
  getCurrentExecutionFile: () => getCurrentExecutionFile,
  matchElementFromPlan: () => matchElementFromPlan,
  parseContextFromWebPage: () => parseContextFromWebPage,
  printReportMsg: () => printReportMsg,
  replaceIllegalPathCharsAndSpace: () => replaceIllegalPathCharsAndSpace,
  reportFileName: () => reportFileName
});
module.exports = __toCommonJS(utils_exports);
var import_ai_model = require("@midscene_spp/core/ai-model");
var import_utils = require("@midscene_spp/core/utils");
var import_env = require("@midscene_spp/shared/env");
var import_extractor = require("@midscene_spp/shared/extractor");
var import_img = require("@midscene_spp/shared/img");
var import_utils2 = require("@midscene_spp/shared/utils");
var import_dayjs = __toESM(require("dayjs"));

// src/web-element.ts
var WebElementInfo = class {
  constructor({
    content,
    rect,
    // page,
    locator,
    id,
    attributes,
    indexId,
    xpaths
  }) {
    this.content = content;
    this.rect = rect;
    this.center = [
      Math.floor(rect.left + rect.width / 2),
      Math.floor(rect.top + rect.height / 2)
    ];
    this.locator = locator;
    this.id = id;
    this.attributes = attributes;
    this.indexId = indexId;
    this.xpaths = xpaths;
  }
};

// src/common/utils.ts
async function parseContextFromWebPage(page, _opt) {
  (0, import_utils2.assert)(page, "page is required");
  if (page._forceUsePageContext) {
    return await page._forceUsePageContext();
  }
  const url = await page.url();
  (0, import_utils.uploadTestInfoToServer)({ testUrl: url });
  let screenshotBase64;
  let tree;
  await Promise.all([
    page.screenshotBase64().then((base64) => {
      screenshotBase64 = base64;
    }),
    page.getElementsNodeTree().then(async (treeRoot) => {
      tree = treeRoot;
    })
  ]);
  const webTree = (0, import_extractor.traverseTree)(tree, (elementInfo) => {
    const { rect, id, content, attributes, locator, indexId } = elementInfo;
    return new WebElementInfo({
      rect,
      locator,
      id,
      content,
      attributes,
      indexId
    });
  });
  (0, import_utils2.assert)(screenshotBase64, "screenshotBase64 is required");
  const elementsInfo = (0, import_extractor.treeToList)(webTree);
  const size = await page.size();
  if (size.dpr && size.dpr > 1) {
    screenshotBase64 = await (0, import_img.resizeImgBase64)(screenshotBase64, {
      width: size.width,
      height: size.height
    });
  }
  return {
    content: elementsInfo,
    tree: webTree,
    size,
    screenshotBase64,
    url
  };
}
function reportFileName(tag = "web") {
  const reportTagName = (0, import_env.getAIConfig)(import_env.MIDSCENE_REPORT_TAG_NAME);
  const dateTimeInFileName = (0, import_dayjs.default)().format("YYYY-MM-DD_HH-mm-ss");
  const uniqueId = (0, import_utils2.uuid)().substring(0, 8);
  return `${reportTagName || tag}-${dateTimeInFileName}-${uniqueId}`;
}
function printReportMsg(filepath) {
  (0, import_utils2.logMsg)(`Midscene - report file updated: ${filepath}`);
}
function getCurrentExecutionFile(trace) {
  const error = new Error();
  const stackTrace = trace || error.stack;
  const pkgDir = process.cwd() || "";
  if (stackTrace) {
    const stackLines = stackTrace.split("\n");
    for (const line of stackLines) {
      if (line.includes(".spec.") || line.includes(".test.") || line.includes(".ts") || line.includes(".js")) {
        const match = line.match(/(?:at\s+)?(.*?\.(?:spec|test)\.[jt]s)/);
        if (match?.[1]) {
          const targetFileName = match[1].replace(pkgDir, "").trim().replace("at ", "");
          return targetFileName;
        }
      }
    }
  }
  return false;
}
var testFileIndex = /* @__PURE__ */ new Map();
function generateCacheId(fileName) {
  let taskFile = fileName || getCurrentExecutionFile();
  if (!taskFile) {
    taskFile = (0, import_utils2.uuid)();
    console.warn(
      "Midscene - using random UUID for cache id. Cache may be invalid."
    );
  }
  if (testFileIndex.has(taskFile)) {
    const currentIndex = testFileIndex.get(taskFile);
    if (currentIndex !== void 0) {
      testFileIndex.set(taskFile, currentIndex + 1);
    }
  } else {
    testFileIndex.set(taskFile, 1);
  }
  return `${taskFile}-${testFileIndex.get(taskFile)}`;
}
var ERROR_CODE_NOT_IMPLEMENTED_AS_DESIGNED = "NOT_IMPLEMENTED_AS_DESIGNED";
function replaceIllegalPathCharsAndSpace(str) {
  return str.replace(/[/\\:*?"<>| ]/g, "-");
}
function forceClosePopup(page, debug) {
  page.on("popup", async (popup) => {
    if (!popup) {
      console.warn("got a popup event, but the popup is not ready yet, skip");
      return;
    }
    const url = await popup.url();
    console.log(`Popup opened: ${url}`);
    if (!popup.isClosed()) {
      try {
        await popup.close();
      } catch (error) {
        debug(`failed to close popup ${url}, error: ${error}`);
      }
    } else {
      debug(`popup is already closed, skip close ${url}`);
    }
    if (!page.isClosed()) {
      try {
        await page.goto(url);
      } catch (error) {
        debug(`failed to goto ${url}, error: ${error}`);
      }
    } else {
      debug(`page is already closed, skip goto ${url}`);
    }
  });
}
function matchElementFromPlan(planLocateParam, tree) {
  if (!planLocateParam) {
    return void 0;
  }
  if (planLocateParam.id) {
    return (0, import_extractor.getNodeFromCacheList)(planLocateParam.id);
  }
  if (planLocateParam.bbox) {
    const centerPosition = {
      x: Math.floor((planLocateParam.bbox[0] + planLocateParam.bbox[2]) / 2),
      y: Math.floor((planLocateParam.bbox[1] + planLocateParam.bbox[3]) / 2)
    };
    let element = (0, import_ai_model.elementByPositionWithElementInfo)(tree, centerPosition);
    if (!element) {
      element = (0, import_extractor.generateElementByPosition)(centerPosition);
    }
    return element;
  }
  return void 0;
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  ERROR_CODE_NOT_IMPLEMENTED_AS_DESIGNED,
  forceClosePopup,
  generateCacheId,
  getCurrentExecutionFile,
  matchElementFromPlan,
  parseContextFromWebPage,
  printReportMsg,
  replaceIllegalPathCharsAndSpace,
  reportFileName
});

//# sourceMappingURL=utils.js.map