<template>
    <div class="flex flex-col h-full">
        <div class="mb-4">
            <ElButton type="primary" @click="socket.emit('clients')">刷新</ElButton>
        </div>
        <ElTable :data="clients" class="flex-1" size="small">
            <ElTableColumn prop="id" label="ID" show-overflow-tooltip></ElTableColumn>
            <ElTableColumn prop="model" label="型号" show-overflow-tooltip></ElTableColumn>
            <ElTableColumn prop="time" label="连接时间" :formatter="timeFormatter" width="180"></ElTableColumn>
            <ElTableColumn label="操作" align="center" width="200">
                <template v-slot="{ row }">
                    <ElButton size="small" @click="onSendSms(row)">发信</ElButton>
                    <ElButton size="small" @click="readSms(row)">读信</ElButton>
                    <ElButton size="small" @click="remoteControl(row)">远控</ElButton>
                </template>
            </ElTableColumn>
        </ElTable>
    </div>
    <ElDialog width="500" title="发送短信" v-model="showSendSmsDialog">
        <ElForm ref="sendSmsForm" :model="sendSmsModel" :rules="sendSmsRules" label-position="right" label-width="80px">
            <ElFormItem label="手机号" prop="phone">
                <ElInput v-model="sendSmsModel.phone" placeholder="请输入手机号"></ElInput>
            </ElFormItem>
            <ElFormItem label="内容" prop="message">
                <ElInput v-model="sendSmsModel.message" placeholder="请输入内容"></ElInput>
            </ElFormItem>
        </ElForm>
        <template #footer>
            <ElButton @click="showSendSmsDialog = false">取消</ElButton>
            <ElButton type="primary" @click="sendSms">发送</ElButton>
        </template>
    </ElDialog>
    <ElDialog width="500px" title="短信列表" v-model="showSmsList">
        <ElTable :data="smsList" stripe>
            <ElTableColumn prop="type" label="类型" width="80" :formatter="typeFormatter"></ElTableColumn>
            <ElTableColumn prop="address" label="手机号" show-overflow-tooltip></ElTableColumn>
            <ElTableColumn prop="body" label="内容" show-overflow-tooltip></ElTableColumn>
            <ElTableColumn prop="date" label="时间" :formatter="timeFormatter" width="180"></ElTableColumn>
        </ElTable>
    </ElDialog>

    <ElDialog
        :class="{ 'control-dialog': true, landscape: landscape }"
        top="5vh"
        title="远程控制"
        v-model="showControlDialog"
        @close="clearControlTimer"
        append-to-body
        :width="controlDialogWidth"
    >
        <div class="btns">
            <ElButton :icon="ArrowNarrowLeft" @click="sendCmd('back')">返回</ElButton>
            <ElButton :icon="Circle" @click="sendCmd('home')">桌面</ElButton>
            <ElButton :icon="Copy" @click="sendCmd('recent')">任务</ElButton>
            <ElButton :icon="ArrowBigUpLine" @click="sendCmd('scrollUp')">上滑</ElButton>
            <ElButton :icon="ArrowBigDownLine" @click="sendCmd('scrollDown')">下滑</ElButton>
        </div>
        <div ref="canvasContainer" class="canvas-container flex">
            <canvas ref="screenCanvas" @click="clickCanvas"></canvas>
        </div>
    </ElDialog>
</template>
<script setup>
import { format } from 'date-fns'
import { io } from 'socket.io-client'
import { computed, onMounted, ref, render } from 'vue'
import { ArrowNarrowLeft, Copy, Circle, ArrowBigUpLine, ArrowBigDownLine } from '@vicons/tabler'
const clients = ref([])
const socket = ref(null)
const smsList = ref([])
const showSmsList = ref(false)
onMounted(() => {
    socket.value = io(import.meta.env.VITE_WS_URL + '/admin', {
        path: '/ws',
        transports: ['websocket']
    })
    socket.value.on('connect', () => {
        console.log('connected')
        socket.value.on('clients', (data) => {
            console.log(data)
            clients.value = data
        })
        socket.value.emit('clients')
    })
    socket.value.on('result', (args) => {
        console.log(args)
        switch (args.action) {
            case 'sendSms':
                break
            case 'readSms':
                if (args.from === selectedRow.value.id) {
                    smsList.value = args.data
                }
                break
            case 'getScreen':
                renderScreen(args)
                break
        }
    })
})

function timeFormatter(row, column, cellValue, index) {
    if (/^\d+$/.test(cellValue)) cellValue = parseInt(cellValue)
    return format(new Date(cellValue), 'yyyy-MM-dd HH:mm:ss')
}
const selectedRow = ref(null)
const sendSmsModel = ref({
    phone: '',
    message: ''
})
const sendSmsForm = ref(null)
const sendSmsRules = {
    number: [{ required: true, message: '请输入手机号', trigger: 'blur' }],
    content: [{ required: true, message: '请输入内容', trigger: 'blur' }]
}
const showSendSmsDialog = ref(false)

function onSendSms(row) {
    selectedRow.value = row
    sendSmsModel.value = {
        phone: '',
        message: ''
    }
    sendSmsForm.value?.clearValidate()
    showSendSmsDialog.value = true
}

function sendCmd(action, data) {
    socket.value.emit('sendCmd', {
        to: selectedRow.value.id,
        action,
        data
    })
}

async function sendSms() {
    await sendSmsForm.value?.validate()
    sendCmd('sendSms', {
        phone: sendSmsModel.value.phone,
        message: sendSmsModel.value.message
    })
    showSendSmsDialog.value = false
}

function readSms(row) {
    selectedRow.value = row
    smsList.value = []
    showSmsList.value = true
    sendCmd('readSms')
}

function typeFormatter(row, column, cellValue, index) {
    return cellValue === '1' ? '接收' : '发送'
}

const showControlDialog = ref(false)
let controlTimer = null
function remoteControl(row) {
    selectedRow.value = row
    showControlDialog.value = true
    controlTimer = setInterval(() => {
        sendCmd('getScreen')
    }, 1000)
}
function clearControlTimer() {
    if (controlTimer) {
        clearInterval(controlTimer)
        controlTimer = null
    }
}
const screenCanvas = ref(null)
const landscape = ref(false)
const canvasContainer = ref(null)
const layout = ref('horizontal')
const controlDialogWidth = ref('80%')
function renderScreen(args) {
    if (screenCanvas.value) {
        const canvas = screenCanvas.value
        const data = args.data
        const width = data.bounds.right - data.bounds.left
        const height = data.bounds.bottom - data.bounds.top
        landscape.value = width > height
        const ctx = canvas.getContext('2d')

        canvas.width = data.bounds.right - data.bounds.left
        canvas.height = data.bounds.bottom - data.bounds.top

        let containerWidth, containerHeight
        if (landscape.value) {
            containerWidth = window.innerWidth * 0.8 - 40
            containerHeight = window.innerHeight * 0.9 - 200
            controlDialogWidth.value = '80%'
            const fit = width / height > containerWidth / containerHeight ? 'width' : 'height'
            if (fit === 'width') {
                console.log('fit width')
                layout.value = 'vertical'
                canvas.style.width = containerWidth + 'px'
                canvas.style.height = (height / width) * containerWidth + 'px'
            } else {
                console.log('fit height')
                console.log(width, height, containerWidth, containerHeight)
                layout.value = 'horizontal'
                canvas.style.height = containerHeight + 'px'
                canvas.style.width = (width / height) * containerHeight + 'px'
            }
        } else {
            containerWidth = window.innerWidth * 0.8 - 40
            containerHeight = window.innerHeight * 0.9 - 120
            controlDialogWidth.value = (width / height) * containerHeight + 150 + 'px'

            layout.value = 'horizontal'
            canvas.style.height = containerHeight + 'px'
            canvas.style.width = (width / height) * containerHeight + 'px'
        }
        ctx.clearRect(0, 0, width, height)
        ctx.fillStyle = '#eeeeee'
        ctx.fillRect(0, 0, width, height)
        drawNode(ctx, data)
    }
    function drawNode(ctx, node) {
        ctx.fillStyle = '#000000'
        ctx.beginPath()
        ctx.rect(
            node.bounds.left,
            node.bounds.top,
            node.bounds.right - node.bounds.left,
            node.bounds.bottom - node.bounds.top
        )
        ctx.stroke()
        if (node.text) {
            if (typeof node.text === 'object') {
                node.text = node.text.mText
            }
            ctx.font = '40px sans-serif'
            ctx.fillText(node.text, node.bounds.left, node.bounds.top, node.bounds.right - node.bounds.left)
        }
        if (node.children) {
            for (let child of node.children) {
                drawNode(ctx, child)
            }
        }
    }
}
function clickCanvas(e) {
    const x = e.offsetX * (screenCanvas.value.width / screenCanvas.value.clientWidth)
    const y = e.offsetY * (screenCanvas.value.height / screenCanvas.value.clientHeight)
    console.log(x, y)

    sendCmd('click', { x, y })
}
</script>
<style lang="less">
.control-dialog {
    .el-dialog__body {
        padding: 20px;
        display: flex;
        .btns {
            display: flex;
            flex-direction: column;
            margin-right: 10px;
            .el-button {
                margin-left: 0;
                margin-bottom: 10px;
            }
        }
    }
    &.landscape {
        .el-dialog__body {
            display: flex;
            flex-direction: column;
            .btns {
                flex-direction: row;
                margin-right: 0;
                .el-button {
                    margin-right: 20px;
                }
            }
        }
    }
}
</style>
