import { EventEmitter } from 'events';
import { obx, computed } from '@ali/lowcode-editor-core';
import { Designer } from '../designer';
import { DocumentModel, isDocumentModel } from '../document';
import { ProjectSchema, RootSchema } from '@ali/lowcode-types';

export class Project {
  private emitter = new EventEmitter();
  @obx.val readonly documents: DocumentModel[] = [];

  private data: ProjectSchema = { version: '1.0.0', componentsMap: [], componentsTree: [] };

  @obx.ref canvasDisplayMode: 'exclusive' | 'overview' = 'exclusive';

  // TODO: 考虑项目级别 History

  constructor(readonly designer: Designer, schema?: ProjectSchema) {
    this.load(schema);
  }

  @computed get currentDocument() {
    return this.documents.find((doc) => doc.actived);
  }

  /**
   * 获取项目整体 schema
   */
  getSchema(): ProjectSchema {
    return {
      ...this.data,
      // todo: future change this filter
      componentsTree: this.documents.filter((doc) => !doc.isBlank()).map((doc) => doc.schema),
    };
  }

  /**
   * 整体设置项目 schema
   *
   * @param autoOpen true 自动打开文档 string 指定打开的文件
   */
  load(schema?: ProjectSchema, autoOpen?: boolean | string) {
    this.unload();
    // load new document
    this.data = {
      version: '1.0.0',
      componentsMap: [],
      componentsTree: [],
      ...schema,
    };

    if (autoOpen) {
      if (autoOpen === true) {
        // auto open first document or open a blank page
        this.open(this.data.componentsTree[0]);
      } else {
        // auto open should be string of fileName
        this.open(autoOpen);
      }
    }
  }

  /**
   * 卸载当前项目数据
   */
  unload() {
    if (this.documents.length < 1) {
      return;
    }
    this.documents.forEach((doc) => doc.remove());
  }

  /**
   * 分字段设置储存数据，不记录操作记录
   */
  set(
    key:
      | 'version'
      | 'componentsTree'
      | 'componentsMap'
      | 'utils'
      | 'constants'
      | 'i18n'
      | 'css'
      | 'dataSource'
      | string,
    value: any,
  ): void {}

  /**
   * 分字段设置储存数据
   */
  get(
    key:
      | 'version'
      | 'componentsTree'
      | 'componentsMap'
      | 'utils'
      | 'constants'
      | 'i18n'
      | 'css'
      | 'dataSource'
      | string,
  ): any {}

  open(doc?: string | DocumentModel | RootSchema): void {
    if (!doc) {
      const got = this.documents.find((item) => item.isBlank());
      if (got) {
        return got.open();
      }
      doc = new DocumentModel(this);
      this.documents.push(doc);
      return doc.open();
    }
    if (typeof doc === 'string') {
      const got = this.documents.find((item) => item.fileName === doc);
      if (got) {
        return got.open();
      }

      const data = this.data.componentsTree.find((data) => data.fileName === doc);
      if (data) {
        doc = new DocumentModel(this, data);
        this.documents.push(doc);
        doc.open();
      }

      return;
    }

    if (isDocumentModel(doc)) {
      return doc.open();
    }

    doc = new DocumentModel(this, doc);
    this.documents.push(doc);
    doc.open();
  }

  checkExclusive(actived: DocumentModel) {
    this.documents.forEach((doc) => {
      if (doc !== actived) {
        doc.suspense();
      }
    });
    this.emitter.emit('current-document.change', actived);
  }

  closeOthers(opened: DocumentModel) {
    this.documents.forEach((doc) => {
      if (doc !== opened) {
        doc.close();
      }
    });
  }

  onCurrentDocumentChange(fn: (doc: DocumentModel) => void): () => void {
    this.emitter.on('current-document.change', fn);
    return () => {
      this.emitter.removeListener('current-document.change', fn);
    };
  }
  // 通知标记删除，需要告知服务端
  // 项目角度编辑不是全量打开所有文档，是按需加载，哪个更新就通知更新谁，
  // 哪个删除就
}
