import { Component, Emit } from 'vue-property-decorator';
import { EditorBase } from '../../../components';
import { VueLifeCycleProcessing, Watch } from '../../../decorators';
import './json-schema-form-editor.less';

/**
 * JsonSchema表单编辑器插件类
 *
 * @export
 * @class JsonSchemaFormEditor
 * @extends {EditorBase}
 */
@Component({})
@VueLifeCycleProcessing()
export class JsonSchemaFormEditor extends EditorBase {
  /**
   * 默认呈现模式
   *
   * @author zhanghengfeng
   * @date 2023-08-10 18:08:39
   * @type {('edit' | 'preview')}
   */
  defaultMode: 'edit' | 'preview' = 'edit';

  /**
   * 当前呈现模式
   *
   * @author zhanghengfeng
   * @date 2023-08-10 18:08:51
   * @type {('edit' | 'preview')}
   */
  mode: 'edit' | 'preview' = 'edit';

  /**
   * 表单数据
   *
   * @author zhanghengfeng
   * @date 2023-08-10 18:08:43
   * @type {Object}
   */
  formData: Object = {};

  /**
   * schema配置
   *
   * @author zhanghengfeng
   * @date 2023-08-10 18:08:51
   * @type {Object}
   */
  schema: Object = {};

  /**
   * 表单底部配置
   *
   * @author zhanghengfeng
   * @date 2023-08-10 18:08:11
   */
  formFooter = {
    show: false,
  };

  /**
   * 解析错误提示信息
   *
   * @author zhanghengfeng
   * @date 2023-08-10 18:08:33
   * @type {string}
   */
  tips: string = '';

  /**
   * 校验结果
   *
   * @author zhanghengfeng
   * @date 2023-08-10 18:08:45
   * @type {boolean}
   */
  validateResult: boolean = true;

  /**
   * 表单数据Json
   *
   * @author zhanghengfeng
   * @date 2023-08-10 18:08:55
   * @type {string}
   */
  formDataJson: string = '';

  /**
   * 值项名称
   *
   * @author zhanghengfeng
   * @date 2023-08-10 19:08:25
   * @type {string}
   */
  valueItem: string = '';

  /**
   * 值项的值
   *
   * @author zhanghengfeng
   * @date 2023-08-10 19:08:51
   * @type {string}
   */
  valueItemJson: string = '';

  /**
   * 编辑器change事件
   *
   * @author zhanghengfeng
   * @date 2023-08-10 18:08:48
   * @param {({ name: string; value: string | null })} _value
   */
  @Emit('change')
  editorChange(_value: { name: string; value: string | null }): void {}

  /**
   * 编辑器change事件
   *
   * @author zhanghengfeng
   * @date 2023-08-10 18:08:53
   * @param {(string | null)} value
   */
  handleChange(value: string | null) {
    this.editorChange({ name: this.editorInstance.name, value });
  }

  /**
   * 编辑器enter事件
   *
   * @author zhanghengfeng
   * @date 2023-08-10 18:08:03
   */
  handleEnter() {
    this.$emit('enter', arguments);
  }

  /**
   * 编辑器初始化
   *
   * @author zhanghengfeng
   * @date 2023-08-10 18:08:14
   */
  async initEditorBase() {
    await super.initEditorBase();
    const { editorParams } = this.editorInstance;
    if (editorParams) {
      const mode = editorParams.mode;
      if (mode === 'preview') {
        this.defaultMode = mode;
        this.mode = mode;
      }
    }
    const valueItems = this.editorInstance.M.getPSEditorItems;
    if (Array.isArray(valueItems) && valueItems.length) {
      this.valueItem = valueItems[0]?.name;
      this.onContextDataChange();
    }
  }

  /**
   * 设置编辑器的自定义高宽
   *
   * @author zhanghengfeng
   * @date 2023-08-10 18:08:23
   */
  setCustomStyle() {
    const { editorWidth, editorHeight } = this.editorInstance;
    this.customStyle = {};
    this.customStyle.width = editorWidth > 0 ? `${editorWidth}px` : `auto`;
    this.customStyle.height = editorHeight > 300 ? `${editorHeight}px` : `300px`;
  }

  /**
   * 监听编辑器值变化
   *
   * @author zhanghengfeng
   * @date 2023-08-10 18:08:47
   * @return {*}
   */
  @Watch('value', { immediate: true })
  onValueChange() {
    if (this.value) {
      try {
        const value = JSON.parse(this.value);
        if (Object.prototype.toString.call(value) === '[object Object]') {
          this.schema = value;
          this.tips = '';
          return;
        }
      } catch (err) {}
    }
    this.schema = {};
    this.tips = 'Json Schema 解析错误';
  }

  /**
   * 监听表单数据变化
   *
   * @author zhanghengfeng
   * @date 2023-08-10 18:08:17
   */
  @Watch('formData', { immediate: true, deep: true })
  onFormDataChange() {
    this.formDataJson = JSON.stringify(this.formData, null, 2);
  }

  /**
   * 监听上下文data数据变化
   *
   * @author zhanghengfeng
   * @date 2023-08-11 09:08:36
   */
  @Watch('contextData', { immediate: true, deep: true })
  onContextDataChange() {
    if (this.valueItem) {
      if (this.contextData) {
        const value = this.contextData[this.valueItem];
        if (value) {
          if (value !== this.valueItemJson) {
            try {
              this.formData = JSON.parse(value);
              return;
            } catch (err) {}
          } else {
            return;
          }
        }
      }
      this.formData = {};
    }
  }

  /**
   * 监听模式切换按钮点击
   *
   * @author zhanghengfeng
   * @date 2023-08-10 18:08:33
   */
  onToggleButtonClick() {
    this.mode = this.mode === 'edit' ? 'preview' : 'edit';
    if (!this.valueItem) {
      this.formData = {};
    }
  }

  /**
   * 监听表单保存按钮点击
   *
   * @author zhanghengfeng
   * @date 2023-08-10 18:08:16
   * @return {*}
   */
  async save() {
    const form = (this.$refs.form as unknown) as { $$uiFormRef: { validate: () => Promise<boolean> } };
    if (form) {
      try {
        await form.$$uiFormRef?.validate();
        this.validateResult = true;
        if (this.valueItem) {
          this.valueItemJson = JSON.stringify(this.formData);
          this.editorChange({ name: this.valueItem, value: this.valueItemJson });
        }
        return;
      } catch (err) {}
    }
    this.validateResult = false;
  }

  /**
   * 渲染编辑器
   *
   * @author zhanghengfeng
   * @date 2023-08-10 18:08:41
   * @return {*}
   */
  renderEditor() {
    return this.$createElement('app-code-editor', {
      props: {
        name: this.editorInstance.name,
        value: this.value,
        disabled: this.disabled,
        language: 'json',
        isSetLanguage: true,
        ...this.customProps,
      },
      on: {
        change: this.handleChange,
        enter: this.handleEnter,
      },
      style: this.customStyle,
    });
  }

  /**
   * 渲染预览表单
   *
   * @author zhanghengfeng
   * @date 2023-08-10 18:08:49
   * @return {*}
   */
  renderForm() {
    return <div class='json-schema-form-editor-form'>{this.tips ? this.tips : <vue-form ref='form' v-model={this.formData} schema={this.schema} formFooter={this.formFooter}></vue-form>}</div>;
  }

  render() {
    if (!this.editorIsLoaded) {
      return null;
    }
    return (
      <div class='json-schema-form-editor'>
        <div class='json-schema-form-editor-header'>
          {this.defaultMode === 'edit' ? (
            <el-button class='json-schema-form-editor__button' type='primary' size='small' on-click={this.onToggleButtonClick}>
              {this.mode === 'edit' ? '预览表单' : '返回编辑'}
            </el-button>
          ) : null}
          {this.mode === 'edit' ? null : (
            <el-popover append-to-body={false} placement='bottom-end'>
              {this.validateResult && !this.valueItem ? <pre class='json-schema-form-editor-form__data'>{this.formDataJson}</pre> : null}
              <el-button slot='reference' type='primary' size='small' on-click={this.save}>
                保存
              </el-button>
            </el-popover>
          )}
        </div>
        <div class='json-schema-form-editor-content'>{this.mode === 'edit' ? this.renderEditor() : this.renderForm()}</div>
      </div>
    );
  }
}
