/**
 * Extension Base Class
 * 扩展基类 - 所有节点、标记、插件扩展的基础
 *
 * 参考：apps/outline/shared/editor/lib/Extension.ts
 */

import type {
  Schema,
  NodeSpec,
  MarkSpec,
  Plugin,
  Command,
  EditorState,
  InputRule,
  ExtensionType,
  ExtensionOptions,
  SlashMenuItem,
  ToolbarItem,
} from './types';

export abstract class Extension<Options extends ExtensionOptions = ExtensionOptions> {
  protected options: Options;

  constructor(options?: Partial<Options>) {
    this.options = {
      ...this.defaultOptions,
      ...options,
    } as Options;
  }

  // ============================================================================
  // 抽象属性 - 子类必须实现
  // ============================================================================

  /** 扩展唯一名称 */
  abstract get name(): string;

  /** 扩展类型 */
  abstract get type(): ExtensionType;

  // ============================================================================
  // 可选属性 - 子类可覆盖
  // ============================================================================

  /** 默认选项 */
  get defaultOptions(): Options {
    return {} as Options;
  }

  // ============================================================================
  // Schema 定义 - 节点和标记扩展需要实现
  // ============================================================================

  /**
   * 获取 ProseMirror NodeSpec（仅节点扩展）
   */
  get schema(): NodeSpec | MarkSpec | null {
    return null;
  }

  // ============================================================================
  // 插件 - 返回 ProseMirror 插件数组
  // ============================================================================

  /**
   * 获取此扩展提供的 ProseMirror 插件
   */
  plugins(_schema: Schema): Plugin[] {
    return [];
  }

  // ============================================================================
  // 输入规则 - Markdown 快捷输入
  // ============================================================================

  /**
   * 获取此扩展的输入规则（Markdown 语法转换等）
   */
  inputRules(_schema: Schema): InputRule[] {
    return [];
  }

  // ============================================================================
  // 快捷键 - 返回快捷键映射
  // ============================================================================

  /**
   * 获取此扩展的快捷键绑定
   */
  keys(_schema: Schema): Record<string, Command> {
    return {};
  }

  // ============================================================================
  // 斜杠菜单 - 返回斜杠命令
  // ============================================================================

  /**
   * 获取此扩展在斜杠菜单中的命令
   */
  slashMenuItems(_schema: Schema): SlashMenuItem[] {
    return [];
  }

  // ============================================================================
  // 工具栏 - 返回工具栏按钮
  // ============================================================================

  /**
   * 获取此扩展在工具栏中的按钮
   */
  toolbarItems(_schema: Schema): ToolbarItem[] {
    return [];
  }

  // ============================================================================
  // 生命周期钩子
  // ============================================================================

  /**
   * 扩展初始化时调用
   */
  onInit?(): void;

  /**
   * 扩展销毁时调用
   */
  onDestroy?(): void;

  /**
   * 编辑器状态更新时调用
   */
  onUpdate?(_state: EditorState): void;

  /**
   * 编辑器聚焦时调用
   */
  onFocus?(): void;

  /**
   * 编辑器失焦时调用
   */
  onBlur?(): void;
}

// ============================================================================
// 专用基类
// ============================================================================

/**
 * 节点扩展基类
 */
export abstract class NodeExtension<
  Options extends ExtensionOptions = ExtensionOptions,
> extends Extension<Options> {
  get type(): ExtensionType {
    return 'node';
  }

  abstract get schema(): NodeSpec;
}

/**
 * 标记扩展基类
 */
export abstract class MarkExtension<
  Options extends ExtensionOptions = ExtensionOptions,
> extends Extension<Options> {
  get type(): ExtensionType {
    return 'mark';
  }

  abstract get schema(): MarkSpec;
}

/**
 * 插件扩展基类
 */
export abstract class PluginExtension<
  Options extends ExtensionOptions = ExtensionOptions,
> extends Extension<Options> {
  get type(): ExtensionType {
    return 'plugin';
  }

  abstract plugins(schema: Schema): Plugin[];
}
