import { FormController } from '@ibiz-template/controller';
import {
  FormDRUIPartModel,
  FormDetailModel,
  FormGroupPanelModel,
  FormItemModel,
  FormModel,
} from '@ibiz-template/model';
import { useNamespace } from '@ibiz-template/vue-util';
import { defineComponent, PropType, CreateElement, VNode } from 'vue';
import '@ibiz-template/theme/style/components/widgets/form/form.scss';

/**
 * 根据类型绘制表单成员
 *
 * @author lxm
 * @date 2022-08-23 16:08:31
 * @param {FormDetailModel} detail 成员模型
 * @param {FormController} controller 表单控制器
 * @returns {*}
 */
function renderByDetailType(
  h: CreateElement,
  detail: FormDetailModel,
  controller: FormController,
): VNode | undefined {
  if ((detail as FormItemModel).source.hidden) {
    return;
  }
  const commonProps = {
    modelData: detail,
    controller: controller.details[detail.source.name],
  };
  const provider = controller.providers[detail.source.name];
  if (!provider) {
    <div>
      暂未支持的表单项类型: {detail.source.detailType}或找不到对应适配器
    </div>;
  }
  return h(
    provider.component,
    {
      props: {
        ...commonProps,
      },
      key: detail.id,
    },
    (detail as FormGroupPanelModel).children?.map(child => {
      return renderByDetailType(h, child, controller);
    }),
  );
}

export const FormControl = defineComponent({
  name: 'FormControl',
  props: {
    modelData: {
      type: FormModel,
      required: true,
    },
    context: { type: Object as PropType<IContext>, required: true },
    controller: {
      type: Object as PropType<FormController>,
      required: true,
    },
  },
  setup(props) {
    const ns = useNamespace('form');

    const c = props.controller;

    return { ns, c };
  },
  render(h) {
    return (
      <control-layout modelData={this.c.model}>
        {this.c.complete && (
          <div class={this.ns.b()}>
            <form-page modelData={this.c.model}>
              {this.$props.modelData.children.map(page => {
                const grouppanel = page.children.find(
                  app => app.source.detailType === 'GROUPPANEL',
                );
                const druipart = page.children.find(
                  app => app.source.detailType === 'DRUIPART',
                ) as FormDRUIPartModel;
                const isDruipart = grouppanel && !!druipart;
                return (
                  <form-page-item
                    key={page.id}
                    caption={page.source.caption}
                    model-data={page}
                    controller={this.c.details[page.source.name]}
                    class={this.ns.is('grouppanel-druipart', isDruipart)}
                  >
                    {page.children.map(detail =>
                      renderByDetailType(h, detail, this.c),
                    )}
                  </form-page-item>
                );
              })}
            </form-page>
          </div>
        )}
      </control-layout>
    );
  },
});