<template>
    <div class="pd10">
        <el-card>
            <el-form ref="formRef" inline :rules="rules" :model="form" label-width="120px" class="form-four">
                <el-form-item label="页面名称:" prop="pageName">
                    <el-input
                        maxlength="32"
                        show-word-limit
                        v-model.trim="form.pageName"
                        placeholder="请输入页面名称"
                    ></el-input>
                </el-form-item>

                <el-form-item label="页面排序:" prop="sort">
                    <el-input
                        maxlength="32"
                        show-word-limit-number
                        v-model.trim.number="form.sort"
                        :min="0"
                        :step="1"
                        step-strictly
                        style="width: 100%"
                    />
                </el-form-item>

                <el-form-item label="备注:" class="top">
                    <el-input
                        maxlength="300"
                        show-word-limit
                        type="textarea"
                        :rows="1"
                        placeholder="请输入内容"
                        v-model.trim="form.remark"
                    ></el-input>
                </el-form-item>
                <el-form-item>
                    <div style="width: 100%; display: flex; justify-content: end">
                        <el-button type="primary" icon="el-icon-Check" @click="onSubmit">保存</el-button>
                        <back-component />
                    </div>
                </el-form-item>
            </el-form>
        </el-card>
        <el-card class="mt10" :style="height">
            <div style="display: flex">
                <div style="width: 605px; overflow: auto" :style="indicatorHeight" class="mr10">
                    <el-collapse v-model="activeNames" :expand-icon-position="position">
                        <el-collapse-item
                            v-for="item in treeComponents"
                            :key="item.id"
                            :title="item.name"
                            :name="item.id"
                        >
                            <el-collapse v-model="activeNames1" class="ml20">
                                <el-collapse-item v-for="k in item.children" :key="k.id" :title="k.name" :name="k.id">
                                    <div class="Box">
                                        <div
                                            v-for="(s, index) in k.children"
                                            :key="index"
                                            class="mr10 mb10 imgBox"
                                            draggable="true"
                                            unselectable="on"
                                            @drag="drag(s)"
                                            @dragend="dragEnd(s)"
                                        >
                                            <div class="textName">{{ s.name }}</div>
                                            <img :src="s.image" style="width: 180px" />
                                        </div>
                                    </div>
                                </el-collapse-item>
                            </el-collapse>
                        </el-collapse-item>
                    </el-collapse>
                </div>
                <div style="flex: 1" ref="wrapper">
                    <GridLayout
                        class="GridLayout"
                        ref="gridLayout"
                        v-model:layout="layout"
                        style="width: 100%"
                        :style="{ height: GridHeight + 'px' }"
                        :row-height="rowHeight"
                        :col-num="12"
                        :vertical-compact="false"
                    >
                        <template #item="{ item }">
                            <div class="imgBox">
                                <div class="textName">{{ item.name }}</div>
                                <img
                                    :src="getImg(item.path)"
                                    :style="{
                                        height:
                                            item.h * rowHeight -
                                            (item.h == 1
                                                ? 30
                                                : item.h == 2
                                                ? 20
                                                : item.h == 3
                                                ? 10
                                                : item.h == 4
                                                ? -0
                                                : item.h == 5
                                                ? -10
                                                : -20) +
                                            'px'
                                    }"
                                />
                                <CloseBold class="remove" @click="removeItem(item.i)" />
                            </div>
                            <!-- <span class="text">{{ `${item?.name}` }}</span>
                            -->
                        </template>
                    </GridLayout>
                </div>
            </div>
        </el-card>
    </div>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import BackComponent from '@/components/icon/back/index.vue'
import { mainHeight } from '@/utils/layout'
import type { CollapseIconPositionType } from 'element-plus'
import { componentTree } from '@/api/user-boot/user'
import { GridLayout, GridItem } from 'grid-layout-plus'
import { throttle } from 'lodash-es'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Tools, CloseBold } from '@element-plus/icons-vue'
import { addDashboard, updateDashboard, queryById } from '@/api/system-boot/csstatisticalset'
import html2canvas from 'html2canvas'
const { go } = useRouter()
const { query } = useRoute()
const height = mainHeight(108)
const indicatorHeight = mainHeight(128)
const rowHeight = ref(0)
const GridHeight = ref(0)
const position = ref<CollapseIconPositionType>('left')
const form: any = reactive({
    pageName: '',
    thumbnail: '',
    containerConfig: [],
    sort: '100',
    id: '',
    remark: ''
})
const activeNames = ref([])
const activeNames1 = ref([])
const rules = {
    pageName: [{ required: true, message: '请输入页面名称', trigger: 'blur' }],
    projectIds: [{ required: true, message: '请选择工程页面', trigger: 'change' }],
    sort: [{ required: true, message: '请输入排序', trigger: 'blur' }]
}
const formRef = ref()
const layout: any = ref([
    // { x: 0, y: 0, w: 4, h: 2, i: '0', name: '', path: '' },
    // { x: 4, y: 0, w: 4, h: 2, i: '1', name: '', path: '' },
    // { x: 8, y: 0, w: 4, h: 2, i: '2', name: '', path: '' },
    // { x: 0, y: 0, w: 4, h: 2, i: '3', name: '', path: '' },
    // { x: 4, y: 0, w: 4, h: 2, i: '4', name: '', path: '' },
    // { x: 8, y: 0, w: 4, h: 2, i: '5', name: '', path: '' },
    // { x: 0, y: 0, w: 4, h: 2, i: '6', name: '', path: '' },
    // { x: 4, y: 0, w: 4, h: 2, i: '7', name: '', path: '' },
    // { x: 8, y: 0, w: 4, h: 2, i: '8', name: '', path: '' }
])
const treeComponents: any = ref([]) //组件树
const treeComponentsCopy: any = ref([]) //组件树
const info = () => {
    activeNames.value = []
    activeNames1.value = []
    componentTree().then(res => {
        treeComponents.value = res.data
        activeNames.value = treeComponents.value.map(item => item.id)
        res.data.forEach(item => {
            item.children.forEach(k => {
                activeNames1.value.push(k.id)
            })
        })
        treeComponentsCopy.value = tree2List(JSON.parse(JSON.stringify(res.data)), 0)
    })

    if (query.id) {
        queryById({ id: query.id }).then(res => {
            layout.value = JSON.parse(res.data.containerConfig)
            form.pageName = res.data.pageName
            form.sort = res.data.sort
            form.remark = res.data.remark
            form.id = res.data.id
        })
    }
}

// 扁平化树
const tree2List = (list: any, id: any) => {
    //存储结果的数组
    let arr: any = []
    // 遍历 tree 数组
    list.forEach((item: any) => {
        item.uPid = id
        item.uId = Math.random() * 1000
        // 判断item是否存在children
        if (!item.children) return arr.push(item)
        // 函数递归，对children数组进行tree2List的转换
        const children = tree2List(item.children, item.uId)
        // 删除item的children属性
        delete item.children
        // 把item和children数组添加至结果数组
        //..children: 意思是把children数组展开
        arr.push(item, ...children)
    })
    // 返回结果数组
    return arr
}
// 删除拖拽
const removeItem = (id: string) => {
    const index = layout.value.findIndex(item => item.i === id)

    if (index > -1) {
        layout.value.splice(index, 1)
    }
}
const wrapper = ref<HTMLElement>()
const gridLayout = ref<InstanceType<typeof GridLayout>>()

const mouseAt = { x: -1, y: -1 }

function syncMousePosition(event: MouseEvent) {
    mouseAt.x = event.clientX
    mouseAt.y = event.clientY
}

const dropId = 'drop'
const dragItem = { x: -1, y: -1, w: 4, h: 2, i: '' }

const drag = throttle(row => {
    // console.log("🚀 ~ drag ~ row:", row)

    const parentRect = wrapper.value?.getBoundingClientRect()

    if (!parentRect || !gridLayout.value) return

    const mouseInGrid =
        mouseAt.x > parentRect.left &&
        mouseAt.x < parentRect.right &&
        mouseAt.y > parentRect.top &&
        mouseAt.y < parentRect.bottom

    if (mouseInGrid && !layout.value.find(item => item.i === dropId)) {
        layout.value.push({
            x: (layout.value.length * 2) % 6,
            y: layout.value.length + 6, // puts it at the bottom
            w: 4,
            h: 2,
            i: dropId
        })
    }

    const index = layout.value.findIndex(item => item.i === dropId)

    if (index !== -1) {
        const item = gridLayout.value.getItem(dropId)

        if (!item) return

        try {
            item.wrapper.style.display = 'none'
        } catch (e) {}

        Object.assign(item.state, {
            top: mouseAt.y - parentRect.top,
            left: mouseAt.x - parentRect.left
        })
        const newPos = item.calcXY(mouseAt.y - parentRect.top, mouseAt.x - parentRect.left)

        if (mouseInGrid) {
            gridLayout.value.dragEvent('dragstart', dropId, newPos.x, newPos.y, dragItem.h, dragItem.w)
            dragItem.i = String(index)
            dragItem.x = layout.value[index].x
            dragItem.y = layout.value[index].y
        } else {
            gridLayout.value.dragEvent('dragend', dropId, newPos.x, newPos.y, dragItem.h, dragItem.w)
            layout.value = layout.value.filter(item => item.i !== dropId)
        }
    }
})

function dragEnd(row: any) {
    console.log('🚀 ~ drag ~ row:', row)
    const parentRect = wrapper.value?.getBoundingClientRect()

    if (!parentRect || !gridLayout.value) return

    const mouseInGrid =
        mouseAt.x > parentRect.left &&
        mouseAt.x < parentRect.right &&
        mouseAt.y > parentRect.top &&
        mouseAt.y < parentRect.bottom

    if (mouseInGrid) {
        gridLayout.value.dragEvent('dragend', dropId, dragItem.x, dragItem.y, dragItem.h, dragItem.w)
        layout.value = layout.value.filter(item => item.i !== dropId)
    } else {
        return
    }

    layout.value.push({
        x: dragItem.x,
        y: dragItem.y,
        w: dragItem.w,
        h: dragItem.h,
        i: dragItem.i,
        name: row.name,
        path: row.path,
        icon: row.icon,
        timeKey: row.timeKey
    })
    gridLayout.value.dragEvent('dragend', dragItem.i, dragItem.x, dragItem.y, dragItem.h, dragItem.w)
    const item = gridLayout.value.getItem(dropId)
    if (!item) return
    try {
        item.wrapper.style.display = ''
    } catch (e) {}
}
// 保存
const onSubmit = () => {
    if (layout.value.length == 0) {
        return ElMessage.warning('页面设计不能为空!')
    }
    const maxValue = Math.max(...layout.value.map(item => item.y + item.h))
    if (maxValue > 6) {
        return ElMessage.warning('组件不能超出当前容器!')
    }

    formRef.value.validate(async (valid: boolean) => {
        let url = ''
        await html2canvas(document.querySelector('.GridLayout'), {
            useCORS: true
        }).then(canvas => {
            url = canvas.toDataURL('image/png')
        })

        if (valid) {
            if (form.id == '') {
                addDashboard({ ...form, containerConfig: JSON.stringify(layout.value), thumbnail: url }).then(
                    (res: any) => {
                        ElMessage.success('新增页面成功!')
                        go(-1)
                    }
                )
            } else {
                updateDashboard({ ...form, containerConfig: JSON.stringify(layout.value), thumbnail: url }).then(
                    (res: any) => {
                        ElMessage.success('修改页面成功!')
                        go(-1)
                    }
                )
            }
        }
    })
}
const getImg = throttle((path: string) => {
    if (path != undefined) return treeComponentsCopy.value.filter(item => item.path == path)[0]?.image
})
onMounted(() => {
    info()

    GridHeight.value = wrapper.value?.offsetWidth / 1.77777
    rowHeight.value = GridHeight.value / 6 - 11.5
    document.documentElement.style.setProperty('--GridLayout-height', rowHeight.value + 10 + 'px')
    document.addEventListener('dragover', syncMousePosition)
})

onBeforeUnmount(() => {
    document.removeEventListener('dragover', syncMousePosition)
})
// onMounted(() => {

//     // document.addEventListener('dragover', syncMousePosition)
// })
</script>
<style lang="scss" scoped>
.form-four {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    .el-form-item {
        display: flex;
        flex: 1;
        align-items: center;
        .el-form-item__content {
            width: 100%;
            flex: 1;
            .el-select,
            .el-cascader,
            .el-input__inner,
            .el-date-editor {
                width: 100%;
            }
        }
    }
}
:deep(.el-card__body) {
    padding: 20px 20px 12px;
}
.Box {
    display: flex;
    flex-wrap: wrap;
}
.imgBox {
    // padding: 10px;
    display: flex;
    flex-direction: column;

    box-shadow: var(--el-box-shadow-light);
    --el-card-border-color: var(--el-border-color-light);
    --el-card-border-radius: 4px;
    --el-card-padding: 20px;
    --el-card-bg-color: var(--el-fill-color-blank);
    background-color: var(--el-card-bg-color);
    border: 1px solid var(--el-card-border-color);
    border-radius: var(--el-card-border-radius);
    color: var(--el-text-color-primary);
    overflow: hidden;
    transition: var(--el-transition-duration) 0.3s;
    .textName {
        padding: 2px 5px;
        background-color: var(--el-color-primary);
        color: #fff;
    }
    user-select: none; /* 标准属性 */
    -webkit-user-select: none; /* Chrome/Safari */
    -moz-user-select: none; /* Firefox */
    -ms-user-select: none; /* IE/Edge */
}
.vgl-layout {
    background-color: #eee;
}

.remove {
    position: absolute;
    top: 5px;
    right: 2px;
    width: 16px;
    color: #fff;
    cursor: pointer;
}

.vgl-layout::before {
    position: absolute;
    width: calc(100% - 5px);
    height: calc(100% - 5px);
    margin: 5px;
    content: '';
    background-image: linear-gradient(to right, lightgrey 1px, transparent 1px),
        linear-gradient(to bottom, lightgrey 1px, transparent 1px);
    background-repeat: repeat;
    background-size: calc(calc(100% - 5px) / 12) var(--GridLayout-height);
}

:deep(.vgl-item:not(.vgl-item--placeholder)) {
    background-color: #fff;
    border: 1px solid black;
}
</style>
