import { JSONValue, JSExpression, JSFunction } from './base';
import {
  ComponentDescription,
  ComponentProp,
  ComponentEvent,
  ComponentSlot
} from './assets';

/**
 * 组件属性描述
 */
export type PropsSchema = Record<string, JSONValue | JSExpression>;

/**
 * 事件修饰符
 */
export type EventModifier =
  | 'stop'
  | 'prevent'
  | 'capture'
  | 'self'
  | 'once'
  | 'passive';

/**
 * 事件描述
 */
export interface EventSchema {
  // 处理句柄
  handler: JSFunction;
  // 修饰符
  modifiers?: Array<EventModifier>;

  params?: string[];
}

/**
 * 指令描述
 * @link https://cn.vuejs.org/guide/reusability/custom-directives.html#directive-hooks
 */
export interface DirectiveSchema {
  arg?: string;
  modifiers?: string[];
  value?: JSExpression;
  // 扩展设置，v-for 需要用到
  extend?: Record<string, any>;
}

/**
 * 组件事件集合
 */
export type EventsSchema = Record<string, EventSchema>;

/**
 * 组件定义
 */
export interface ComponentDefine {
  props?: ComponentProp[];
  events?: ComponentEvent[];
  slots?: ComponentSlot[];
}

/**
 * 组件描述
 */
export interface NodeSchema {
  /**
   * 节点id
   */
  id?: string;

  key?: string;
  /**
   * 组件名称 或 HTML标签名称, 特殊名称：slot、template
   */
  name: string;
  /**
   * 组件属性
   */
  props?: PropsSchema;
  /**
   * 事件
   */
  events?: Record<string, EventSchema>;
  /**
   * 指令
   */
  directives?: Record<string, DirectiveSchema>;
  /**
   * 样式名 className
   */
  className?: string | JSExpression;
  /**
   * 内联样式 style
   */
  style?: Record<string, any> | JSExpression;
  /**
   * 组件引用名
   */
  ref?: string;

  /**
   * 插槽名称 <slot name='SlotName' v-bind="props"></slot>
   */
  slotName?: string;

  /**
   * 插槽参数名, <template v-slot:[SlotName]="{...slotParams}"></template>
   */
  slotParams?: string[];

  /**
   * 子节点
   */
  children?: Array<NodeSchema | BlockSchema> | string | JSExpression;
}

export interface WatchSchema {
  deep?: boolean;
  immediate?: boolean;
  handler: JSFunction;
}

export interface RootSchema extends NodeSchema {
  /**
   * 出码页面文件名称
   */
  fileName: string;

  /**
   * 状态数据
   */
  state?: Record<string, JSONValue | JSExpression>;

  /**
   * 计算属性
   */
  computed?: Record<string, JSFunction>;

  /**
   * 侦听器
   */
  watch?: Record<string, WatchSchema>;
  /**
   * 方法集
   */
  methods?: Record<string, JSFunction>;

  dataSources?: Record<string, IFileDataSource>;

  /**
   * 生命周期集
   */
  lifeCycles?: Record<string, JSFunction>;
  /**
   * css 代码
   */
  css?: string;
  /**
   * 引用组件映射
   */
  componentMap?: Record<string, ComponentDescription>;

  /**
   * 组件定义 props emits slots 配置
   */
  define?: ComponentDefine;

  /**
   * 发布信息
   */
  release?: any;
}

export interface SchemaRelease {
  /**
   * 版本号 预留，待实现
   */
  version?: string;

  /**
   * 作者信息，预留，待实现
   */
  author?: any;

  /**
   * zuixin发布时间
   */
  publishTime?: string;

  /**
   * 备注说明
   */
  description?: string;

  /**
   * 截图保存路径，待定
   */
  screenshot?: string;
}

export interface BlockSchema extends RootSchema {
  name: 'Block';
  // 文件标题
  title?: string;
}

export interface DocumentSchema extends RootSchema {
  name: 'Page';
  /**
   * 页面访问路由路径
   */
  routePath: string;
}

export interface DocumentSummarySchema {
  /**
   * 页面标识id
   */
  id?: string;

  name: 'Page';

  /**
   * 出码页面文件名称
   */
  fileName: string;
  /**
   * 页面访问路由路径
   */
  routePath: string;
}

export interface BlockSummarySchema {
  /**
   * 页面标识id
   */
  id?: string;

  name: 'Block';

  /**
   * 出码页面文件名称
   */
  fileName: string;
}

export interface PorjectSchema {
  /**
   * 项目名称
   */
  name?: string;
  /**
   * 项目描述标题
   */
  title?: string;

  /**
   * 页面或区块列表
   */
  files?: Array<IFileSchema>;

  /**
   * 项目数据源
   */
  dataSources?: Array<DataSourceSchema>;

  /**
   * 主页页面id
   */
  homePageId?: string;
}

export type IFileSchema = DocumentSchema | BlockSchema;

export type IFileSummarySchema = DocumentSummarySchema | BlockSummarySchema;

/**
 * 数据源类型： 接口、数据魔方、数据配置
 */
export type DataSourceType = 'api' | 'cube' | 'meta';

/**
 * 数据源项
 */
export interface DataSourceItem {
  id: string;
  params: Record<string, any>;
}

export interface DataSourceSchema {
  type: DataSourceType;
  items?: Array<DataSourceItem>;
}

export interface IFileDataSource extends DataSourceItem {
  type: DataSourceType;
  // 数据转换函数
  transform?: JSFunction | ((res?: any) => any);
}
