<template>
    <div class="scene-list-overview">
        <el-row>
            <el-col :span="12" class="card-box" style="padding-right: 7.5px; margin-top: 5px">
                <el-card>
                    <div slot="header">
                        <span>{{ $t('scene.overview.324354-0') }}</span>
                    </div>
                    <div class="el-table el-table--enable-row-hover el-table--medium">
                        <div class="prop-box-info" id="scenePropBox">
                            <div class="left-pic">
                                <el-image style="width: 100px; height: 100px" :src="sceneModels.imgUrl ? baseUrl + sceneModels.imgUrl : require('@/assets/images/scene-info.png')" fit="fill"></el-image>
                            </div>
                            <div class="right-message">
                                <div class="title">{{ sceneModels.sceneModelName }}</div>
                                <div class="info-item">
                                    <label>{{ $t('scene.overview.324354-1') }}</label>
                                    <span>{{ sceneModels.deptName }}</span>
                                </div>
                                <div class="info-item">
                                    <label>{{ $t('scene.overview.324354-2') }}</label>
                                    <span v-if="sceneModels.cusDeviceList && sceneModels.cusDeviceList.length > 0">
                                        <el-tag class="tag-wrap" size="small" v-for="(item, index) in sceneModels.cusDeviceList" :key="index">{{ item.name }}</el-tag>
                                    </span>
                                </div>
                                <div class="info-item">
                                    <label>{{ $t('scene.overview.324354-3') }}</label>
                                    <span>{{ sceneModels.updateTime }}</span>
                                </div>
                            </div>
                        </div>
                    </div>
                </el-card>
            </el-col>

            <el-col :span="12" class="card-box" style="padding-left: 7.5px; margin-top: 5px">
                <el-card>
                    <div slot="header">
                        <span>{{ $t('scene.overview.324354-4') }}</span>
                    </div>
                    <div class="el-table el-table--enable-row-hover el-table--medium">
                        <div class="prop-box-attr" :style="{ height: scenePropBoxHeight + 'px' }">
                            <div class="num-empty">
                                {{ $t('scene.overview.324354-5') }}
                                <br />
                                <br />
                                <br />
                                <br />
                                <el-image style="width: 493px; height: 29px" :src="require('@/assets/images/scene-basic-attr-flow.png')" fit="fill"></el-image>
                            </div>
                        </div>
                    </div>
                </el-card>
            </el-col>

            <el-col :span="24" class="card-box" style="margin-bottom: 15px">
                <el-card>
                    <div slot="header">
                        <span>{{ $t('scene.overview.324354-6') }}</span>
                    </div>
                    <div class="el-table--enable-row-hover el-table--medium">
                        <el-form :model="queryParams" ref="queryForm" :inline="true" label-width="68px">
                            <el-form-item prop="sceneModelDeviceId">
                                <el-select v-model="queryParams.sceneModelDeviceId" :placeholder="$t('scene.overview.324354-8')" clearable>
                                    <el-option v-for="(item, index) in sceneModels.sceneModelDeviceVOList" :key="index" :label="item.name" :value="item.id"></el-option>
                                </el-select>
                            </el-form-item>
                            <el-form-item prop="sourceName">
                                <el-input v-model="queryParams.sourceName" :placeholder="$t('scene.overview.324354-12')" clearable />
                            </el-form-item>
                            <el-form-item>
                                <el-button type="primary" icon="el-icon-search" @click="handleQuery">{{ $t('search') }}</el-button>
                                <el-button icon="el-icon-refresh" @click="handleResetQuery">{{ $t('reset') }}</el-button>
                            </el-form-item>
                        </el-form>
                        <el-table v-loading="loading" :data="variableList" style="width: 100%; margin-top: 10px" :border="false">
                            <el-table-column prop="id" :label="$t('scene.overview.324354-13')" width="100"></el-table-column>
                            <el-table-column prop="sceneModelDeviceName" :label="$t('scene.overview.324354-7')" align="left" min-width="140"></el-table-column>
                            <el-table-column prop="slaveName" :label="$t('scene.overview.324354-9')" align="left" min-width="120"></el-table-column>
                            <el-table-column prop="sourceName" :label="$t('scene.overview.324354-11')" align="left" min-width="130"></el-table-column>
                            <el-table-column prop="updateTime" :label="$t('scene.overview.324354-14')" align="center" width="175"></el-table-column>
                            <el-table-column prop="value" :label="$t('scene.overview.324354-15')" align="center" min-width="130">
                                <template slot-scope="scope">
                                    <span>
                                        {{ scope.row.valueName === '' || scope.row.valueName === null ? '-' : scope.row.valueName }}
                                        {{ scope.row.value !== '' && scope.row.value !== null ? scope.row.unit : '' }}
                                        <i v-if="scope.row.isReadonly === 0" style="cursor: pointer; color: #1890ff" class="el-icon-edit" v-hasPermi="['iot:service:invoke']" @click="handleEditVariable(scope.row)"></i>
                                    </span>
                                </template>
                            </el-table-column>
                            <el-table-column :label="$t('opation')" align="center" width="100">
                                <template slot-scope="scope">
                                    <el-button size="mini" type="text" @click="handleQueryHistory(scope.row)">{{ $t('scene.overview.324354-16') }}</el-button>
                                </template>
                            </el-table-column>
                        </el-table>
                        <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getVariableList" />
                    </div>
                </el-card>
            </el-col>
        </el-row>

        <!-- 设备类型下发弹框 -->
        <el-dialog :title="$t('device.realTime-status.099127-26')" :visible.sync="dialogValue" width="480px">
            <el-form>
                <el-form-item v-for="(item, index) in opationList" :label="`${item.label}：`" :key="index" label-width="120px">
                    <el-input
                        v-model="funVal[item.key]"
                        :precision="0"
                        :controls="false"
                        @input="justNumber(item)"
                        type="number"
                        v-if="
                            item.dataTypeName == 'integer' ||
                            item.dataTypeName == 'decimal' ||
                            (item.dataTypeName == 'array' && item.arrayType == 'integer') ||
                            (item.dataTypeName == 'array' && item.arrayType == 'decimal')
                        "
                        style="width: 200px"
                    ></el-input>
                    <el-input
                        v-model="funVal[item.key]"
                        :precision="0"
                        :controls="false"
                        :placeholder="$t('plzInput')"
                        type="text"
                        v-if="item.dataTypeName == 'string' || (item.dataTypeName == 'array' && item.arrayType == 'string')"
                        style="width: 230px"
                        @input="justNumber(item)"
                    ></el-input>
                    <el-select v-if="item.dataTypeName == 'enum' || item.dataTypeName == 'bool'" v-model="funVal[item.key]" @change="changeSelect()">
                        <el-option v-for="option in item.options" :key="option.value" :label="option.label" :value="option.value"></el-option>
                    </el-select>
                    <span
                        v-if="
                            (item.dataTypeName == 'integer' ||
                                item.dataTypeName == 'decimal' ||
                                (item.dataTypeName == 'array' && item.arrayType == 'integer') ||
                                (item.dataTypeName == 'array' && item.arrayType == 'decimal')) &&
                            item.unit &&
                            item.unit != 'un' &&
                            item.unit != '/'
                        "
                    >
                        ({{ item.unit }})
                    </span>
                    <span
                        style="margin-left: 5px"
                        v-if="
                            item.dataTypeName == 'integer' ||
                            item.dataTypeName == 'decimal' ||
                            (item.dataTypeName == 'array' && item.arrayType == 'integer') ||
                            (item.dataTypeName == 'array' && item.arrayType == 'decimal')
                        "
                    >
                        ({{ item.min }} ~ {{ item.max }})
                    </span>
                </el-form-item>
                <el-form-item style="display: none">
                    <el-input v-model="functionName"></el-input>
                </el-form-item>
            </el-form>
            <span slot="footer" class="dialog-footer">
                <el-button @click="dialogValue = false">{{ $t('cancel') }}</el-button>
                <el-button type="primary" @click="sendService" :loading="btnLoading" :disabled="!canSend">{{ $t('confirm') }}</el-button>
            </span>
        </el-dialog>
    </div>
</template>

<script>
import { mapState } from 'vuex';
import moment from 'moment';
import { getSceneModelDataList } from '@/api/scene/list.js';
import { serviceInvokeReply, serviceInvoke } from '@/api/iot/runstatus.js';
import { getOrderControl } from '@/api/iot/control';

export default {
    name: 'SceneListOverView',
    computed: {
        ...mapState({
            sidebarStatus: (state) => state.app.sidebar.opened,
        }),
    },
    props: {
        sceneModels: {
            type: Object,
            default: null,
        },
    },
    data() {
        return {
            baseUrl: process.env.VUE_APP_BASE_API,
            scenePropBoxHeight: 150, // 场景基本属性窗口高度
            loading: false,
            queryParams: {
                sceneModelId: null,
                sceneModelDeviceId: null,
                slaveName: '',
                sourceName: '',
                pageNum: 1,
                pageSize: 10,
            },
            variableList: [], // 变量列表
            funVal: {},
            chooseFun: {},
            deviceInfo: {},
            //下发的设备
            serialNumber: '',
            opationList: [],
            functionName: '',
            total: 0, // 总条数
            canSend: false, //是否可以下发，主要判断数值在不在范围
            btnLoading: false,
            dialogValue: false,
            form: {},
        };
    },
    watch: {
        // 检测系统菜单栏状态
        sidebarStatus() {
            this.calculateScenePropBoxHeight();
        },
        sceneModels: {
            deep: true,
            handler(newVal, oldVal) {
                if (newVal) {
                    this.getVariableList();
                }
            },
        },
    },
    mounted() {
        // 获取高度
        this.calculateScenePropBoxHeight();
        window.addEventListener('resize', this.calculateScenePropBoxHeight, true);
        this.connectMqtt();
    },
    methods: {
        // 获取窗体高度
        calculateScenePropBoxHeight() {
            setTimeout(() => {
                let originalHeight = document.getElementById('scenePropBox').offsetHeight;
                this.scenePropBoxHeight = parseFloat(originalHeight);
            }, 500);
        },
        // 获取变量情况列表
        getVariableList() {
            this.loading = true;
            this.queryParams.sceneModelId = this.$route.query.sceneModelId;
            let { sceneModelDeviceId, ...pres } = this.queryParams;
            if (sceneModelDeviceId === '-1') {
                sceneModelDeviceId = '';
            }
            const params = { sceneModelDeviceId, ...pres };
            getSceneModelDataList(params).then((res) => {
                if (res.code === 200) {
                    this.variableList = res.rows.map((item) => {
                        if (item.variableType == 1) {
                            return {
                                ...item,
                                valueName: this.getValueName(item),
                                dataTypeName: item.datatype.type || '',
                            };
                        } else {
                            return {
                                ...item,
                                valueName: this.getValueName(item),
                            };
                        }
                    });
                    this.total = res.total;
                }
                this.loading = false;
            });
        },
        //判断输入是否超过范围
        justNumber(val) {
            this.canSend = true;
            this.opationList.some((item) => {
                if (item.max < this.funVal[item.key] || item.min > this.funVal[item.key]) {
                    this.canSend = false;
                    return true;
                }
            });
            this.$forceUpdate();
        },
        //下拉选择修改触发
        changeSelect() {
            this.$forceUpdate();
        },
        // 封装操作列表
        getOpationList(item) {
            this.opationList = [];
            let options = [];
            this.funVal = {};
            const datatype = item.datatype;
            if (datatype.type == 'enum') {
                options =
                    datatype.enumList?.map((option) => {
                        return {
                            label: option.text,
                            value: option.value + '',
                        };
                    }) || [];
            }
            if (datatype.type == 'bool') {
                options = [
                    {
                        label: datatype.falseText || '',
                        value: '0',
                    },
                    {
                        label: datatype.trueText || '',
                        value: '1',
                    },
                ];
            }
            this.opationList.push({
                dataTypeName: datatype.type,
                arrayType: datatype.arrayType,
                label: item.sourceName,
                key: item.identifier,
                max: parseInt(datatype?.max || 100),
                min: parseInt(datatype?.min || -100),
                options: options,
                value: item.value,
            });
            this.opationList.forEach((item) => {
                let value = item.value;
                if (item.datatype == 'integer' || item.datatype == 'decimal' || (item.dataTypeName == 'array' && item.arrayType == 'integer') || (item.dataTypeName == 'array' && item.arrayType == 'decimal')) {
                    value = parseInt(value);
                }
                this.funVal[item.key] = value;
            });
        },

        // 搜索按钮操作
        handleQuery() {
            this.queryParams.pageNum = 1;
            this.getVariableList();
        },
        // 重置按钮操作
        handleResetQuery() {
            this.resetForm('queryForm');
            this.handleQuery();
        },
        async editVariable(item) {
            //判断是否有权限
            const params = {
                deviceId: item.deviceId,
                modelId: item.datasourceId,
            };
            const response = await getOrderControl(params);
            if (response.code != 200) {
                this.$message({
                    type: 'warning',
                    message: response.msg,
                });
                return;
            }
            //这里兼容子设备的下发，在网关设备下发的时候选择实际子设备的编号
            this.serialNumber = item.serialNumber;
            let title = '';
            if (item.status !== 3) {
                if (item.status !== 3) {
                    title = this.$t('device.device-variable.930930-0');
                } else if (item.status === 2) {
                    title = this.$t('device.device-variable.930930-1');
                } else {
                    title = this.$t('device.device-variable.930930-2');
                }
                this.$message({
                    type: 'warning',
                    message: title,
                });
                return;
            }
            this.dialogValue = true;
            this.canSend = true;
            this.funVal = {};
            this.chooseFun = item;
            this.getOpationList(item);
        },
        // 编辑变量值
        async handleEditVariable(item) {
            if (item.variableType !== 1) {
                this.$prompt(this.$t('scene.overview.324354-17'), this.$t('edit'), {
                    confirmButtonText: this.$t('confirm'),
                    cancelButtonText: this.$t('cancel'),
                    inputPattern: /\S/,
                    inputErrorMessage: this.$t('scene.overview.324354-17'),
                    inputPlaceholder: item.value,
                }).then(({ value }) => {
                    const command = {};
                    command[item.identifier] = value;
                    const data = {
                        sceneModelId: item.sceneModelId,
                        variableType: item.variableType,
                        serialNumber: item.serialNumber,
                        productId: item.productId,
                        remoteCommand: command,
                        identifier: item.identifier,
                        modelName: item.modelName,
                        isShadow: item.status != 3,
                        type: item.type,
                    };
                    serviceInvoke(data).then((res) => {
                        if (res.code === 200) {
                            item.updateTime = moment(new Date()).format('YYYY-MM-DD HH:mm:ss');
                            item.value = value;
                        }
                    });
                });
            } else {
                this.editVariable(item);
            }
        },
        // 发送指令
        async sendService() {
            try {
                let params = this.funVal;
                const pas = {
                    serialNumber: this.serialNumber,
                    identifier: this.chooseFun.identifier,
                    remoteCommand: params,
                };
                this.btnLoading = true;
                if (this.deviceInfo.protocolCode === 'MODBUS-TCP' || this.deviceInfo.protocolCode === 'MODBUS-RTU') {
                    await serviceInvokeReply(pas).then((response) => {
                        if (response.code === 200) {
                            this.$message({
                                type: 'success',
                                message: this.$t('device.running-status.866086-25'),
                            });
                        } else {
                            this.$message.error(response.msg);
                        }
                    });
                } else {
                    await serviceInvoke(pas).then((response) => {
                        if (response.code === 200) {
                            this.$message({
                                type: 'success',
                                message: this.$t('device.running-status.866086-25'),
                            });
                        } else {
                            this.$message.error(response.msg);
                        }
                    });
                }
                for (let i = 0; i < this.variableList.length; i++) {
                    if (this.variableList[i].identifier == this.chooseFun.identifier) {
                        const variable = Object.values(this.funVal)[0];
                        this.variableList[i].value = variable;
                        this.variableList[i].valueName = this.getValueName(this.variableList[i]);
                        break;
                    }
                }
            } finally {
                this.btnLoading = false;
                this.dialogValue = false;
            }
        },
        getValueName(item) {
            //返回的数据
            let res = item.value || '-';
            //需要解析的类型
            const optionsType = ['bool', 'enum'];
            //如果有datatype并且需要解析就遍历解析
            if (item.datatype) {
                switch (item.datatype.type) {
                    case 'bool':
                        if (0 == item.value) res = item.datatype.falseText;
                        if (1 == item.value) res = item.datatype.trueText;
                        break;
                    case 'enum':
                        item.datatype.enumList?.some((enumOpt) => {
                            if (enumOpt.value == item.value) {
                                res = enumOpt.text;
                                return true;
                            }
                        });
                        break;
                }
            }
            return res;
        },

        // 查询历史数据
        handleQueryHistory(item) {
            this.$router.push({
                path: '/dataCenter/history',
                query: {
                    sceneModelId: item.sceneModelId,
                    sceneModelDeviceId: item.sceneModelDeviceId,
                    identifier: item.identifier,
                    activeName: 'scene',
                },
            });
        },
        // 连接Mqtt消息服务器
        async connectMqtt() {
            if (this.$mqttTool.client == null) {
                await this.$mqttTool.connect();
            }
            // 删除所有message事件监听器
            this.$mqttTool.client.removeAllListeners('message');
            // 添加message事件监听器
            this.mqttCallback();
        },
        // Mqtt回调处理
        mqttCallback() {
            const _this = this;
            this.$mqttTool.client.on('message', (topic, message, buffer) => {
                let topics = topic.split('/');
                let productId = topics[1];
                let deviceNum = topics[2];
                message = JSON.parse(message.toString());
                if (!message) {
                    return;
                }
                console.log('接收到【物模型】主题：', topic);
                console.log('接收到【物模型】内容：', message);
                if (topic.endsWith('ws/service')) {
                    // 更新列表中设备的属性
                    message = message.message;
                    message.forEach((mes) => {
                        _this.variableList.forEach((vari) => {
                            this.$busEvent.$emit('updateData', {
                                serialNumber: topics[2],
                                productId: vari.productId,
                                data: message,
                            });
                            // 更新列表中设备的状态
                            if (vari.serialNumber === deviceNum) {
                                if (vari.identifier === mes.id) {
                                    vari.value = mes.value;
                                    vari.valueName = this.getValueName(vari);
                                    vari.updateTime = moment(new Date()).format('YYYY-MM-DD HH:mm:ss');
                                }
                            }
                        });
                    });
                }
                if (topic.endsWith('scene/report')) {
                    // 更新列表中设备的属性
                    message.forEach((mes) => {
                        _this.variableList.forEach((vari) => {
                            const identifier = vari.identifier;
                            if (identifier === mes.id) {
                                vari.value = mes.value;
                                vari.valueName = this.getValueName(vari);
                                vari.updateTime = moment(new Date()).format('YYYY-MM-DD HH:mm:ss');
                            }
                        });
                    });
                }
            });
        },
    },
};
</script>

<style lang="scss" scoped>
.scene-list-overview {
    width: 100%;

    .card-box {
        padding: 0;
        margin: 15px 0 0;
    }

    .prop-box-info {
        display: flex;

        .left-pic {
            margin-right: 20px;
        }

        .right-message {
            width: 100%;

            .title {
                font-size: 12px;
                color: #333;
                font-weight: 600;
                margin-bottom: 20px;
            }

            .info-item {
                display: flex;
                align-items: flex-start;
                margin-bottom: 15px;
                font-size: 12px;
                font-weight: 400;
                color: #333;

                label {
                    color: #666;
                    width: 80px;
                    flex-shrink: 0;
                    font-weight: normal;
                }

                .tag-wrap {
                    margin-bottom: 5px;
                    margin-right: 5px;
                    cursor: pointer;
                }
            }
        }
    }

    .prop-box-attr {
        .num-empty {
            width: 100%;
        }

        .num-area {
            display: flex;
            flex-wrap: wrap;

            .num-props {
                margin-right: 10px;
                margin-bottom: 10px;
                display: flex;
                width: calc(33% - 20px);
                font-size: 12px;

                .name-div {
                    white-space: nowrap;
                    text-overflow: ellipsis;
                    overflow: hidden;
                    word-break: break-all;
                    flex-shrink: 0;
                    max-width: 50%;
                }

                .value-part {
                    margin-left: 15px;
                }
            }
        }
    }
}
</style>
