import { Vue, Component, Emit, Prop } from 'vue-property-decorator';
import { on } from '@ibizstudio-ex/runtime';
import { OpenParams } from './interface/open-params';
import { ModelData } from '../model-data';
import { ModelService } from '../service/model-service';
import draggable from 'vuedraggable';
import './model-clipboard-import-view.less';
import { ModelClipboardController } from '../controller/model-clipboard-controller';

/**
 * 粘贴板模型导入视图
 *
 * @export
 * @class ModelClipboardImportView
 * @extends {Vue}
 */
@Component({
  components: {
    draggable,
  },
})
export class ModelClipboardImportView extends Vue {
  /**
   * 是否已经关闭
   *
   * @type {boolean}
   * @memberof ModelClipboardImportView
   */
  @Prop({ default: false })
  isClose!: boolean;

  /**
   * 已拖入的模型
   *
   * @protected
   * @type {ModelData[]}
   * @memberof ModelClipboardImportView
   */
  protected items: ModelData[] = [];

  /**
   * 已经导入的条数
   *
   * @protected
   * @type {ModelData[]}
   * @memberof ModelClipboardImportView
   */
  protected importItems: ModelData[] = [];

  /**
   * 所有模型
   *
   * @protected
   * @type {any[]}
   * @memberof ModelClipboardImportView
   */
  protected models: any[] = [];

  /**
   * 是否在编辑界面更改过模型
   *
   * @protected
   * @type {boolean}
   * @memberof ModelClipboardImportView
   */
  protected isModelChange: boolean = false;

  /**
   * 参数
   *
   * @protected
   * @type {OpenParams}
   * @memberof ModelClipboardImportView
   */
  protected param: OpenParams = {};

  /**
   * 字符创模型
   *
   * @protected
   * @type {string}
   * @memberof ModelClipboardImportView
   */
  protected modelStr: string = '';

  /**
   * 模型操作服务
   *
   * @protected
   * @type {ModelService}
   * @memberof ModelClipboardImportView
   */
  protected service: ModelService = ModelService.getInstance();

  /**
   * 是否正在加载状态
   *
   * @protected
   * @type {boolean}
   * @memberof ModelClipboardImportView
   */
  protected isLoading: boolean = false;

  /**
   * 组件创建完毕
   *
   * @memberof ModelClipboardImportView
   */
  created(): void {
    on(document, 'keydown', (e: KeyboardEvent) => {
      if (e.keyCode === 27 && this.isLoading === false) {
        this.closeView();
      }
    });
  }

  /**
   * 设置参数
   *
   * @param {*} param
   * @memberof StudioModelEditor
   */
  setParam(param: OpenParams): void {
    if (param && !Object.is(JSON.stringify(param), JSON.stringify(this.param))) {
      this.param = param;
      this.clearAllData();
    }
  }

  /**
   * 发送关闭事件
   *
   * @protected
   * @memberof ModelClipboardImportView
   */
  @Emit('close')
  protected close(): void {
    this.$Message.destroy();
  }

  /**
   * 保存完毕事件
   *
   * @protected
   * @memberof ModelClipboardImportView
   */
  @Emit('saved')
  protected saved(): void {}

  /**
   * 关闭当前视图
   *
   * @protected
   * @memberof ModelClipboardImportView
   */
  protected closeView(): void {
    if (this.isModelChange) {
      this.$Modal.confirm({
        title: '确认关闭',
        content: '模型数据已变更，确认关闭吗?',
        onOk: () => {
          this.close();
          this.clearAllData();
        },
      });
    } else {
      this.close();
    }
  }

  /**
   * 模型编辑变更
   *
   * @protected
   * @param {string} val
   * @memberof ModelClipboardImportView
   */
  protected modelChange(val: string): void {
    if (!Object.is(this.modelStr, val)) {
      this.modelStr = val;
      this.isModelChange = true;
    }
  }

  /**
   * 重置模型，此发放提供给模型重新计算使用。用于覆盖人为修改内容
   *
   * @protected
   * @param {string} val
   * @memberof ModelClipboardImportView
   */
  protected initModel(val: string): void {
    this.modelStr = val;
    this.isModelChange = false;
  }

  /**
   * 清除当前已计算模型
   *
   * @protected
   * @memberof ModelClipboardImportView
   */
  protected clearModel(): void {
    if (this.isModelChange) {
      this.$Modal.confirm({
        title: '确认清除?',
        content: '模型数据已变更，将同已拖入模型一同清空，确认清除吗？',
        onOk: () => {
          this.clearAllData();
        },
      });
    } else {
      this.clearAllData();
    }
  }

  /**
   * 拖入模型变更
   *
   * @protected
   * @param {*} e
   * @memberof ModelClipboardImportView
   */
  protected dropModelChange(e: any): void {
    if (this.isModelChange) {
      this.$Modal.confirm({
        title: '确认操作?',
        content: '检测到输入框内容已手动修改，该操作后输入框内容将重新计算，确认操作吗？',
        onOk: () => {
          this.calcModeStr();
        },
        onCancel: () => {
          if (e && e.added && e.added.newIndex) {
            this.items.splice(e.added.newIndex, 1);
          }
        },
      });
    } else {
      this.calcModeStr();
    }
  }

  /**
   * 保存模型
   *
   * @protected
   * @param {*} [params={}]
   * @returns {Promise<void>}
   * @memberof ModelClipboardImportView
   */
  protected async saveModel(params: any = {}): Promise<void> {
    this.$Message.destroy();
    try {
      this.models = JSON.parse(this.modelStr);
    } catch (error) {
      this.$Message.error({ content: '模型数据格式异常，请检查!', closable: true, duration: 0 });
      return;
    }
    this.isLoading = true;
    this.importItems = [];
    let isError: boolean = false;
    for (let i = 0; i < this.models.length; i++) {
      const item: any = this.models[i];
      params = { srfdename: this.param.srfDeName, srfmodel: item, srfparentdata: this.param.srfParentData };
      try {
        const res: any = await this.service.saveModel(params, { srfdename: this.param.srfDeName });
        if (res.ok) {
          this.isModelChange = false;
          this.importItems.push(item);
          this.saved();
        } else {
          Vue.prototype.$message({ message: res.statusText, type: 'error', showClose: true, center: true, duration: 0 });
          isError = true;
          break;
        }
      } catch (err: any) {
        if (err) {
          Vue.prototype.$message({ message: err.message, type: 'error', showClose: true, center: true, duration: 0 });
        }
        isError = true;
        break;
      }
    }
    if (!isError) {
      this.$Modal.confirm({
        title: '关闭导入界面?',
        content: '已导入完毕，确认关闭导入界面!',
        onOk: () => {
          this.close();
        },
      });
    }
    setTimeout(() => {
      this.isLoading = false;
    }, 300);
  }

  /**
   * 计算模型文本内容
   *
   * @protected
   * @param {ModelData[]} [items=this.items]
   * @memberof ModelClipboardImportView
   */
  protected calcModeStr(items: ModelData[] = this.items): void {
    this.$Message.warning('编辑框内，模型内容已重新计算!');
    this.models = [];
    items.forEach((item: ModelData) => {
      this.models.push(...item.models);
    });
    try {
      this.initModel(JSON.stringify(this.models, null, 2));
    } catch (error) {
      console.log(error);
    }
  }

  /**
   * 删除拖拽项
   *
   * @protected
   * @param {number} i
   * @memberof ModelClipboardImportView
   */
  protected deleteDropItem(i: number): void {
    this.items.splice(i, 1);
    this.calcModeStr();
  }

  /**
   * 格式化数据
   *
   * @protected
   * @memberof ModelClipboardImportView
   */
  protected formatData(): boolean {
    try {
      this.modelStr = JSON.stringify(JSON.parse(this.modelStr), null, 2);
      return true;
    } catch (error) {
      this.$Message.error({
        content: '格式有误无法格式化，请检查!',
        duration: 2.5,
      });
    }
    return false;
  }

  /**
   * 绘制已拖入模型项
   *
   * @protected
   * @param {ModelData} item
   * @returns {*}
   * @memberof ModelClipboardImportView
   */
  protected renderDragItem(item: ModelData, i: number): any {
    return (
      <div class='model-drag-item'>
        <div class='actions'>
          <div class='action-item delete' on-click={() => this.deleteDropItem(i)}>
            <i class='ivu-icon ivu-icon-md-close' />
          </div>
        </div>
        <div class='title'>{item.title}</div>
        <div class='date'>{item.createdDate}</div>
      </div>
    );
  }

  /**
   * 绘制素材区模型项
   *
   * @protected
   * @param {ModelData} item
   * @returns {*}
   * @memberof ModelClipboardImportView
   */
  protected renderMaterialItem(item: ModelData): any {
    return (
      <div class='model-material-item'>
        <div class='title'>{item.title}</div>
        <div class='date'>{item.createdDate}</div>
      </div>
    );
  }

  /**
   * 绘制内容
   *
   * @returns {*}
   * @memberof ModelClipboardImportView
   */
  render(): any {
    const items: any = ModelClipboardController.getInstance().items.filter((item: ModelData) => {
      if (!Object.is(this.param.srfDeName, item.srfDeName) || this.items.findIndex((self: ModelData) => Object.is(self.uuid, item.uuid)) !== -1) {
        return;
      }
      return item;
    });
    return (
      <el-card
        class='model-clipboard-import-view'
        v-loading={this.isLoading}
        element-loading-text={'数据导入中：' + this.importItems.length + ' / ' + this.models.length}
        element-loading-spinner='el-icon-loading'
        element-loading-background='rgba(0, 0, 0, 0.8)'
      >
        <div slot='header' class='model-clipboard-import-view-header'>
          <span>模型导入</span>
          <i-button title='关闭模型导入窗口' type='text' ghost on-click={() => this.closeView()}>
            关闭
          </i-button>
        </div>
        <div class='model-clipboard-import-view-content'>
          <div class='import-warp'>
            <div class='drop-area'>
              <div class='drop-area-header'></div>
              <draggable class='drop-area-draggable' on-change={(evt: any) => this.dropModelChange(evt)} group={ModelClipboardController.getInstance().draggableOption.group} list={this.items}>
                {this.items.map((item: ModelData, i: number) => {
                  return this.renderDragItem(item, i);
                })}
              </draggable>
              1
              <div v-show={this.items.length === 0} class='drop-tooltip'>
                请从右侧素材区拖入
              </div>
            </div>
            <div class='model-edit'>
              <app-code-editor language='json' key='code-content-ftl' value={this.modelStr} on-change={(val: string) => this.modelChange(val)} codetype='json' height='100%'></app-code-editor>
              <div class='edit-actions'>
                <i-button size='small' title='清空当前已拖入模型' ghost on-click={() => this.clearModel()}>
                  清空
                </i-button>
                <i-button size='small' title='格式化编辑框内JSON数据' ghost on-click={() => this.formatData()}>
                  格式化
                </i-button>
                <i-button size='small' title='导入模型数据' ghost on-click={() => this.saveModel()}>
                  导入
                </i-button>
              </div>
            </div>
          </div>
          <div class='model-material-warp'>
            <div class='model-material-title'>模型素材</div>
            <draggable class='model-material-content' sort={false} group={ModelClipboardController.getInstance().draggableOption.noPutGroup} list={items}>
              {items.map((item: ModelData) => {
                return this.renderMaterialItem(item);
              })}
            </draggable>
            <div v-show={items.length === 0} class='model-material-tooltip'>
              暂无数据
            </div>
          </div>
        </div>
      </el-card>
    );
  }

  /**
   * 清理数据
   *
   * @protected
   * @memberof ModelClipboardImportView
   */
  protected clearAllData(): void {
    this.items = [];
    this.models = [];
    this.importItems = [];
    this.modelStr = '';
    this.isModelChange = false;
  }
}
