<template>
  <IxForm :control="menuForm"
      :control-col="{span:18}"
      :label-col="{span:6}"
      class="menu-detail-form"
      label-align="end"
      layout="horizontal"
      message-tooltip>
    <IxRow>
      <IxCol :span="6">
        <IxFormItem :gutter="[0, 10]" label="上级菜单">
          <IxTreeSelect
              :dataSource="menuTreeDataSource"
              control="pid"
              placeholder="请选择上级菜单"
              show-line
          />
        </IxFormItem>
      </IxCol>
      <IxCol :span="6">
        <IxFormItem
            :gutter="[0, 10]"
            label="类型">
          <IxSelect
              :dataSource="menuCategoryData"
              control="menuCategory"
          />
        </IxFormItem>
      </IxCol>
    </IxRow>
    <IxRow>
      <IxCol :span="6">
        <IxFormItem :gutter="[0,10]" label="菜单名称">
          <IxInput control="title"/>
        </IxFormItem>
      </IxCol>
      <IxCol :span="6">
        <IxFormItem
            :gutter="[0, 10]"
            label="排序">
          <IxInputNumber :min="0" control="sort"/>
        </IxFormItem>
      </IxCol>
    </IxRow>
    <IxRow>
      <IxCol :span="6">
        <IxFormItem
            :gutter="[0, 10]"
            label="路由名称">
          <IxInput :min="0" control="routeName"/>
        </IxFormItem>
      </IxCol>
      <IxCol v-if="status === 'create'" :span="6">
        <IxFormItem
            :gutter="[0, 10]"
            label="资源编码">
          <IxInput :min="0" control="sn"/>
        </IxFormItem>
      </IxCol>
    </IxRow>
    <IxRow>
      <IxCol :span="6">
        <IxFormItem
            :gutter="[0, 10]"
            label="图标">
          <IxPopover closable header="图标列表" placement="bottom" trigger="click">
            <IxInput control="icon"/>
            <template #content>
              <IxTable v-model:selectedRowKeys="selectedRowKeys" :columns="columns" :dataSource="iconTableDataSource" :pagination="pagination" get-key="name"/>
            </template>
          </IxPopover>
        </IxFormItem>
      </IxCol>
    </IxRow>
  </IxForm>
</template>

<script lang="ts" setup>
import { ref } from 'vue'
import {
  useFormGroup,
  Validators
} from '@idux/cdk'
import {
  MenuCategory,
  MenuCategoryDict
} from '@/common/app/contants.ts'
import { TreeSelectNode } from '@idux/components/tree-select/src/types'
import { SelectData } from '@idux/components/select/src/types'
import MenuApi from '@/pages/sys/menus/menu-api.ts'
import Colls from '@/common/utils/colls.ts'
import icons from '@/components/iconfont/icons.ts'
import {
  TableColumn,
  TableColumnSelectable
} from '@idux/components/table'
import { TablePagination } from '@idux/components/table/src/types'
import Iconfont from '@/components/iconfont/Iconfont.vue'

interface IconData {
  name: string
}

const selectedRowKeys = ref<string[]>([])

const iconTableDataSource = ref<IconData[]>(icons.filter((_, i) => {
  return i >= 0 && i < 5
}))
const selectableColumn = reactive<TableColumnSelectable<IconData>>({
  type: 'selectable',
  align: 'center',
  multiple: false,
  showIndex: false,
  trigger: 'click',
  onChange: (selectedKeys) => {
    menuForm.get('icon')?.setValue(selectedKeys[0] as string)
  },
})
const columns: TableColumn<IconData>[] = [
  selectableColumn,
  {
    title: '图标',
    dataKey: 'name',
    customCell: ({record}: { record: IconData }) => {
      return h(Iconfont, {name: record.name as IconfontTypes.name})
    }
  },
  {
    title: '名称',
    dataKey: 'name',
  },
]
const pagination = reactive<TablePagination>({
  pageIndex: 1,
  pageSize: 5,
  total: icons.length,
  size: 'sm',
  showTotal: true,
  onChange(pageIndex: number, pageSize: number) {
    pagination.pageIndex = pageIndex
    pagination.pageSize = pageSize
    iconTableDataSource.value = icons.filter((_, i) => {
      return i >= (pageIndex - 1) * pageSize && i < pageIndex * pageSize
    })
  }
})
const props = withDefaults(defineProps<{ status?: 'create' | 'view' | 'edit' }>(),
    {
      status: 'create',
    }
)

const menuForm = useFormGroup<MenuTypes.MenuForm>({
  pid: [ '' ],
  menuCategory: [ MenuCategory.Page, Validators.required ],
  title: [ '', Validators.required ],
  sort: [ 0 ],
  routeName: [ '' ],
  sn: [ undefined ],
  icon: [ undefined ],
})
const menuCategoryCtrl = menuForm.get('menuCategory')
const routeNameCtrl = menuForm.get('routeName')
menuCategoryCtrl.watchValue(value => {
  if (value === MenuCategory.Page || value === MenuCategory.SubPage) {
    routeNameCtrl.enable()
    routeNameCtrl.setValidators([ Validators.required ])
    routeNameCtrl.validate()
  } else {
    routeNameCtrl.clearValidators()
    routeNameCtrl.setValue('')
    routeNameCtrl.disable()
    routeNameCtrl.validate()
    routeNameCtrl.markAsPristine()
  }
})

const menuCategoryData = computed(() => {
  const data: SelectData[] = []
  for (const key in MenuCategoryDict) {
    data.push({
      key,
      label: MenuCategoryDict[key as keyof typeof MenuCategoryDict],
    })
  }
  return data
})

const menuTreeDataSource = ref<TreeSelectNode[]>()

function updateFormStatus() {
  if (props.status === 'view') {
    menuForm.disable()
  } else if (props.status === 'edit') {
    menuForm.enable()
    menuCategoryCtrl.disable()
    const val = menuCategoryCtrl.getValue()
    if (val !== MenuCategory.Page && val !== MenuCategory.SubPage) {
      routeNameCtrl.disable()
    }
  }
}

watch(() => props.status, updateFormStatus)

defineExpose({
  getValue() {
    return menuForm.getValue()
  },
  setValue(data: MenuTypes.MenuForm) {
    menuForm.setValue(data)
    if (data.icon != null) {
      selectedRowKeys.value = [ data.icon ]
    }
  },
  reset() {
    menuForm.reset()
    MenuApi.list()
        .then(({data}) => {
          menuTreeDataSource.value = Colls.toTree(data.map(it => ({key: it.id, label: it.title, ...it})))
        })
  }
})

onMounted(() => {
  updateFormStatus()
  MenuApi.list()
      .then(({data}) => {
        menuTreeDataSource.value = Colls.toTree(data.map(it => ({key: it.id, label: it.title, ...it})))
      })
})

</script>

<style lang="stylus" scoped>
.menu-detail-form {
  width 100%
  padding 1rem
  margin 1rem 0

  :deep(.ix-row) {
    margin .5rem 0
  }
}

</style>
