import { DashboardController } from '@ibiz-template/controller';
import {
  DashboardModel,
  ContainerPortletModel,
  PortletPartModel,
} from '@ibiz-template/model';
import { useDashboardController, useNamespace } from '@ibiz-template/vue-util';
import {
  defineComponent,
  getCurrentInstance,
  h,
  PropType,
  reactive,
  VNode,
} from 'vue';
import './dashboard-control.scss';

/**
 * 根据类型绘制数据看板成员
 *
 * @author lxm
 * @date 2022-10-14 17:10:42
 * @param {PortletPartModel} model 模型
 * @param {IData} opts 额外参数
 */
function renderPortletByType(
  model: PortletPartModel,
  c: DashboardController,
  opts?: IData,
): VNode {
  const provider = c.providers[model.name];
  const controller = c.portlets[model.name];
  const commonProps = {
    modelData: model,
    controller,
  };

  // 绘制容器
  if (model.source.portletType === 'CONTAINER') {
    const container = model as ContainerPortletModel;
    return h(
      provider.component,
      {
        props: {
          ...commonProps,
        },
        key: model.id,
      },
      container.children.map(child => renderPortletByType(child, c, opts)),
    );
  }

  // 绘制门户部件
  return h(provider.component, {
    props: {
      ...commonProps,
    },
    key: model.id,
  });
}

export const DashboardControl = defineComponent({
  name: 'DashboardControl',
  props: {
    modelData: {
      type: DashboardModel,
      required: true,
    },
    context: { type: Object as PropType<IContext>, required: true },
    params: { type: Object as PropType<IParams>, default: () => ({}) },
  },
  setup(props) {
    const { proxy } = getCurrentInstance()!;
    const c = useDashboardController(
      proxy,
      props.modelData,
      props.context,
      props.params,
    );

    c.nerve.self.evt.on('created', () => {
      Object.values(c.portlets).forEach(portlet => {
        Object.assign(portlet, {
          state: reactive(portlet.state),
        });
      });
    });

    const ns = useNamespace('dashboard');

    return { c, ns };
  },

  render() {
    return (
      <control-layout class={[this.ns.b()]} modelData={this.c.model}>
        {this.c.complete && (
          <app-row
            class={this.ns.e('content')}
            layout={this.modelData.source.getPSLayout()}
          >
            {this.modelData.children.map(child => {
              return (
                <app-col
                  layoutPos={child.source.getPSLayoutPos()}
                  controller={this.c.portlets[child.name].layoutController}
                >
                  {renderPortletByType(child, this.c)}
                </app-col>
              );
            })}
          </app-row>
        )}
      </control-layout>
    );
  },
});