import "../../chunks/chunk.QU3DSPNU.js";
class CemParser {
  /**
   * Loads and parses the CEM file
   */
  static async loadManifest(cemPath = "../../../custom-elements.json") {
    const cemModule = await import(cemPath);
    return cemModule.default;
  }
  /**
   * Extracts modules that contain web components
   */
  static getComponentModules(manifest) {
    return manifest.modules.filter(
      (mod) => mod.declarations?.some((declaration) => {
        const d = declaration;
        return d.tagName && d.customElement === true;
      })
    );
  }
  /**
   * Extracts component data from a JavaScriptModule declaration
   */
  static extractComponentData(mod, declaration) {
    const className = declaration.name;
    const tagName = declaration.tagName;
    return {
      tagName,
      className,
      description: declaration.description,
      outputPath: mod.path,
      sourcePath: mod.path,
      properties: this.extractProperties(declaration),
      events: this.extractEvents(declaration),
      slots: this.extractSlots(declaration),
      methods: this.extractMethods(declaration),
      isFormControl: this.isFormControl(declaration),
      isIconComponent: this.isIconComponent(declaration),
      isLinkComponent: this.isLinkComponent(declaration),
      isCheckboxComponent: this.isCheckboxComponent(tagName),
      subcomponents: this.extractSubcomponents(declaration)
    };
  }
  /**
   * Checks if a component inherits from a specific base class
   */
  static inheritsMembersFrom(declaration, className, modulePath) {
    if (!declaration.members) return false;
    return declaration.members.some(
      (member) => member.inheritedFrom?.name === className && member.inheritedFrom?.module === modulePath
    );
  }
  /**
   * Checks if a component is a form control by looking for properties inherited from GdsFormControlElement
   */
  static isFormControl(declaration) {
    return this.inheritsMembersFrom(
      declaration,
      "GdsFormControlElement",
      "src/components/form/form-control.ts"
    );
  }
  /**
   * Checks if a component is an icon by looking for properties inherited from GdsIcon
   */
  static isIconComponent(declaration) {
    return this.inheritsMembersFrom(
      declaration,
      "GdsIcon",
      "src/components/icon/icon.component.ts"
    );
  }
  /**
   * Checks if a component supports routing by looking for an 'href' property
   */
  static isLinkComponent(declaration) {
    if (!declaration.members) return false;
    return declaration.members.some(
      (member) => member.kind === "field" && member.name === "href" && member.privacy !== "private" && member.privacy !== "protected"
    );
  }
  /**
   * Checks if a component is a checkbox by checking the tag name
   * Checkboxes need special handling to work with boolean checked state instead of string values
   */
  static isCheckboxComponent(tagName) {
    return tagName === "gds-checkbox";
  }
  /**
   * Extracts properties
   */
  static extractProperties(declaration) {
    if (!declaration.members) return [];
    return declaration.members.filter(
      (member) => member.name?.length > 0 && member.kind === "field" && member.privacy !== "private" && member.privacy !== "protected" && !member.readonly && !member.static
    ).map((field) => ({
      kind: "field",
      name: field.name,
      type: field.type,
      defaultValue: field.default,
      description: field.description
    }));
  }
  /**
   * Extracts events
   */
  static extractEvents(declaration) {
    if (!declaration.events) return [];
    return declaration.events.filter((event) => event.name && !event.inheritedFrom).map((event) => ({
      name: event.name,
      // Store original event name
      type: this.mapEventType(event.type?.text, event.name),
      description: event.description
    }));
  }
  /**
   * Extracts slot information
   */
  static extractSlots(declaration) {
    if (!declaration.slots) return [];
    return declaration.slots.map((slot) => ({
      name: slot.name || "default",
      description: slot.description
    }));
  }
  /**
   * Extracts public methods
   */
  static extractMethods(declaration) {
    if (!declaration.members) return [];
    return declaration.members.filter(
      (member) => member.kind === "method" && member.privacy !== "private" && !member.static && !member.inheritedFrom && !member.name.startsWith("_")
    ).map((method) => ({
      name: method.name,
      description: method.description,
      returnType: method.return?.type,
      parameters: method.parameters?.map((param) => ({
        name: param.name,
        type: param.type?.text || "any",
        optional: param.optional || false
      })) || []
    }));
  }
  /**
   * Extracts subcomponent information from custom @subcomponent JSDoc tags
   */
  static extractSubcomponents(declaration) {
    const subcomponents = declaration.subcomponents;
    if (!subcomponents || !Array.isArray(subcomponents) || subcomponents.length === 0) {
      return void 0;
    }
    return subcomponents.map((sub) => ({
      tagName: sub.tagName,
      description: sub.description
    }));
  }
  /**
   * Maps CEM event types to TypeScript types
   */
  static mapEventType(cemType, eventName) {
    if (cemType) {
      if (cemType === "CustomEvent") {
        return "CustomEvent<any>";
      }
      return cemType;
    }
    if (!eventName) return "Event";
    const standardEventMap = {
      click: "MouseEvent",
      dblclick: "MouseEvent",
      mousedown: "MouseEvent",
      mouseup: "MouseEvent",
      mouseover: "MouseEvent",
      mouseout: "MouseEvent",
      mousemove: "MouseEvent",
      mouseenter: "MouseEvent",
      mouseleave: "MouseEvent",
      contextmenu: "MouseEvent",
      keydown: "KeyboardEvent",
      keyup: "KeyboardEvent",
      keypress: "KeyboardEvent",
      focus: "FocusEvent",
      blur: "FocusEvent",
      focusin: "FocusEvent",
      focusout: "FocusEvent",
      input: "InputEvent",
      change: "Event",
      submit: "SubmitEvent",
      reset: "Event",
      scroll: "Event",
      resize: "UIEvent",
      load: "Event",
      unload: "Event",
      error: "ErrorEvent",
      touchstart: "TouchEvent",
      touchend: "TouchEvent",
      touchmove: "TouchEvent",
      touchcancel: "TouchEvent",
      wheel: "WheelEvent",
      drag: "DragEvent",
      dragstart: "DragEvent",
      dragend: "DragEvent",
      dragenter: "DragEvent",
      dragleave: "DragEvent",
      dragover: "DragEvent",
      drop: "DragEvent"
    };
    const standardType = standardEventMap[eventName];
    if (standardType) {
      return standardType;
    }
    if (eventName.startsWith("gds-") || eventName.includes("-")) {
      return "CustomEvent<any>";
    }
    return "Event";
  }
  /**
   * Finds primitives that are re-exported by component modules.
   * 
   * Primitives (like GdsOption, GdsMenuHeading) are internal implementation details
   * but some are re-exported by specific components for public use. For example:
   * - GdsOption is re-exported by GdsDropdown
   * - GdsMenuHeading is re-exported by GdsContextMenu
   * 
   * This method identifies these re-exports and returns the component file path
   * (not the primitive path) so imports point to the re-exporting component.
   * 
   * Design choices:
   * - Only considers *.component.ts files, not index.ts files, to ensure imports
   *   point to the actual component file (e.g., dropdown.component.js not index.js)
   *   because index.ts paths are not tree-shakable
   * - First occurrence wins when a primitive is re-exported by multiple components
   */
  static findReExportedPrimitives(manifest) {
    const reExportedPrimitives = [];
    for (const JavaScriptModule of manifest.modules) {
      if (!JavaScriptModule.path.includes("/components/") || !JavaScriptModule.exports) {
        continue;
      }
      if (JavaScriptModule.path.endsWith("/index.ts")) {
        continue;
      }
      for (const exportDecl of JavaScriptModule.exports) {
        if (exportDecl.declaration?.module?.includes("primitives/")) {
          const primitivePackage = exportDecl.declaration.module;
          let normalizedPath = primitivePackage;
          if (normalizedPath.startsWith("../")) {
            normalizedPath = normalizedPath.replace(/^(\.\.\/)+/, "src/");
          } else if (normalizedPath.startsWith("./")) {
            normalizedPath = normalizedPath.replace(
              /^\.\//,
              JavaScriptModule.path.replace(/\/[^/]+$/, "/")
            );
          }
          const primitiveModule = manifest.modules.find(
            (m) => m.path.includes(normalizedPath)
          );
          if (primitiveModule?.declarations) {
            for (const primitiveDecl of primitiveModule.declarations) {
              if (primitiveDecl.customElement && primitiveDecl.tagName) {
                reExportedPrimitives.push({
                  primitiveName: primitiveDecl.tagName,
                  primitiveClass: primitiveDecl.name,
                  reExportModule: JavaScriptModule.path,
                  reExportPath: JavaScriptModule.path.replace(/^src\//, "").replace(/\.ts$/, ".js")
                });
              }
            }
          }
        }
      }
    }
    return reExportedPrimitives;
  }
  /**
   * Parses all components from the manifest
   */
  static async parseAllComponents(manifestPath) {
    const manifest = await this.loadManifest(manifestPath);
    const componentModules = this.getComponentModules(manifest);
    const reExportedPrimitives = this.findReExportedPrimitives(manifest);
    const components = [];
    for (const JavaScriptModule of componentModules) {
      if (JavaScriptModule.path.includes("/primitives/")) {
        continue;
      }
      for (const declaration of JavaScriptModule.declarations || []) {
        if (declaration.tagName && declaration.customElement === true) {
          const componentData = this.extractComponentData(
            JavaScriptModule,
            declaration
          );
          components.push(componentData);
        }
      }
    }
    const primitiveMap = /* @__PURE__ */ new Map();
    for (const reExported of reExportedPrimitives) {
      if (primitiveMap.has(reExported.primitiveClass)) {
        continue;
      }
      const primitiveModule = manifest.modules.find(
        (m) => m.declarations?.some((d) => d.name === reExported.primitiveClass)
      );
      if (primitiveModule) {
        const primitiveDecl = primitiveModule.declarations?.find(
          (d) => d.name === reExported.primitiveClass
        );
        if (primitiveDecl) {
          const componentData = this.extractComponentData(
            primitiveModule,
            primitiveDecl
          );
          componentData.sourcePath = reExported.reExportModule;
          primitiveMap.set(reExported.primitiveClass, componentData);
        }
      }
    }
    components.push(...primitiveMap.values());
    return { components, reExportedPrimitives };
  }
  /**
   * Parses a single component by tag name
   */
  static async parseComponent(tagName, manifestPath) {
    const { components } = await this.parseAllComponents(manifestPath);
    return components.find((comp) => comp.tagName === tagName) || null;
  }
}
export {
  CemParser
};
