import { css, cx } from "@linaria/core";
import { Tooltip } from "ant-design-vue";
import _ from "lodash";
import { computed, defineComponent } from "vue";
import { any, array, bool, func } from "vue-types";

export interface ColumnItem {
  label?: string;
  component?: ((...args: any[]) => any) | Record<string, any>;
  dataIndex?: string;
  setterIndex?: string;
  props?: { [name: string]: any };
  itemProps?: { [name: string]: any };
  getValue?: (v: any, data?:any) => any;
  isDisable?: (value: any, data: any) => boolean;
  isLoading?: (value: any, data: any) => boolean;
  isVisible?: (value: any, data: any) => boolean;
  changeExtra?: (data: any) => any;
  children?: ColumnItem[];
}

export default defineComponent({
  props: {
    columns: array<ColumnItem>().isRequired,
    editor: any(),
    data: any().isRequired,
    disabled: bool(),
    onChange: func(),
    onChangeEnd: func(),
  },
  setup(props) {
    return () => <FormUI {...props} />;
  },
});

const FormUI = (props: {
  columns: ColumnItem[];
  data: any;
  editor: any;
  disabled?: boolean;
  onChange?: (...arg: any) => void;
  onChangeEnd?: (...arg: any) => void;
}) => {
  const { columns, ...restProps } = props;
  return (
    <>
      {columns?.map((column: ColumnItem, index: number) => {
        if (!column.dataIndex) {
          return renderUI({ props: restProps, column, index });
        }
        return renderFormItem({ column, ...restProps, index });
      })}
    </>
  );
};

const renderUI = ({ props, column, index }: any) => {
  const component = column.component;
  if (component instanceof Function) {
    const params: any = {
      ...props,
      column,
      key: index,
      children: FormUI({ ...props, columns: column.children }),
    };
    return component(params);
  } else {
    return (
      <component {...props} column={column} key={index}>
        <FormUI {...props} columns={column.children} />
      </component>
    );
  }
};

export const renderFormItem = (props: {
  column: ColumnItem;
  index?: number;
  data: any;
  editor: any;
  disabled?: boolean;
  onChange?: (...arg: any) => void;
  onChangeEnd?: (...arg: any) => void;
}) => {
  const { column, data, index, onChange, onChangeEnd } = props;

  // const compValue = computed(() => {
  //   const { data, column } = props;
  //   if (!column.dataIndex) return;
  //   const itemValue = _.get(data, column.dataIndex);
  //   return column.getValue ? column.getValue(itemValue) : itemValue;
  // });

  // const editor = props.editor;
  // const compValue = editor ? editor.commands.get(column.dataIndex) : "";
  // console.log(column.dataIndex, compValue.value);
  
  const compValue = computed(() => {
    const { data, column } = props;
    if (!column.dataIndex) return;
    const itemValue = _.get(data, column.dataIndex);
    return column.getValue ? column.getValue(itemValue, data) : itemValue;
  });

  const changeVal = (value: any, ...args: any[]) => {
    const { column } = props;
    let params = {
      dataIndex: column.dataIndex,
      setterIndex: column.setterIndex,
      value,
      ...args,
    };
    if (column.changeExtra) params = column.changeExtra?.(params);
    onChange?.(params);
    return params;
  };

  const changeValEnd = (value: any, ...args: any[]) => {
    const params = changeVal(value, ...args);
    onChangeEnd?.(params);
  };

  // const isVisible = column.isVisible?.(compValue.value, data);
  // if (column.isVisible && !isVisible) return null;

  // const disabled = props.disabled || column.isDisable?.(compValue.value, data);

  const component = column.component;

  return (
    <div
      key={index}
      class={formItemStyles}
      {...column.itemProps}
      onClick={(e) => e.stopPropagation()}
    >
      {column.label ? (
        <Tooltip title={column.label} placement="top">
          <component
            value={compValue.value}
            {...column.props}
            loading={column.isLoading?.(compValue.value, data)}
            onChange={changeVal}
            onChangeEnd={changeValEnd}
          />
        </Tooltip>
      ) : (
        <component
          value={compValue.value}
          {...column.props}
          loading={column.isLoading?.(compValue.value, data)}
          onChange={changeVal}
          onChangeEnd={changeValEnd}
        />
      )}
    </div>
  );
};

const formItemStyles = css`
  height: 100%;
  margin: 0 6px;
  &.disabled {
    cursor: not-allowed;
  }
`;

export function useFormColumns(columns: ColumnItem[]) {
  return columns;
}
