<template>
  <el-table id="syslogTable" v-addId.table="'syslogServerTable'" :data="props.data" border>
    <!-- 序号 -->
    <el-table-column :label="traduction('EVENT_ORDER')" type="index" width="50" />
    <!-- 服务器地址 -->
    <el-table-column
      :label="traduction('ALARM_REPORT_SERVICE_ADDR')"
      prop="serviceAddr"
      class="service-addr-column"
      min-width="100"
    >
      <template #default="scope">
        <div v-show="!scope.row.isEdit">
          <span :id="'serviceAddr' + scope.$index">{{ scope.row.serviceAddr }}</span>
        </div>
        <div v-show="scope.row.isEdit">
          <el-form
            :ref="setAddrFormRef"
            class="syslog-form"
            :class="{ 'has-error': scope.row.disabled }"
            :model="scope.row"
            :rules="formRules"
            :validate-on-rule-change="false"
            @validate="validateAction(scope.row).action"
          >
            <el-form-item prop="serviceAddr">
              <el-popover
                v-model:visible="popoverVisible.serviceAddr[scope.row.num]"
                popper-class="no-wrap-popover"
                placement="top"
                :teleported="true"
                :content="scope.row.validationAddr.tip"
                trigger="focus"
                trigger-keys
              >
                <template #reference>
                  <el-input
                    v-model="scope.row.serviceAddr"
                    v-addId.input="'addrSection'"
                    v-clearable
                    clearable
                    @focus="focus('serviceAddr', scope.row)"
                    @blur="blur('serviceAddr', scope.row)"
                    @clear="clear('serviceAddr', scope.row)"
                    @input="change('serviceAddr', $event, scope.row)"
                  >
                    <template #suffix>
                      <ErrorIcon />
                      <ClearableIcon />
                    </template>
                  </el-input>
                </template>
              </el-popover>
            </el-form-item>
          </el-form>
        </div>
      </template>
    </el-table-column>
    <!-- 端口 -->
    <el-table-column :label="traduction('SERVICE_PORT')" class="port-column" width="150">
      <template #default="scope">
        <div v-show="!scope.row.isEdit">
          <span :id="'port' + scope.$index">{{ scope.row.port }}</span>
        </div>
        <div v-show="scope.row.isEdit">
          <el-form
            :ref="setPortFormRef"
            class="syslog-form"
            :class="{ 'has-error': scope.row.disabled }"
            :model="scope.row"
            :rules="formRules"
            :validate-on-rule-change="false"
            @validate="validateAction(scope.row).action"
          >
            <el-form-item prop="port">
              <el-popover
                v-model:visible="popoverVisible.port[scope.row.num]"
                popper-class="no-wrap-popover"
                placement="top"
                :teleported="true"
                :content="scope.row.validationPort.tip"
                trigger="focus"
                trigger-keys
              >
                <template #reference>
                  <el-input
                    v-model="scope.row.port"
                    v-addId.input="'portSection' + scope.row.num"
                    v-clearable
                    clearable
                    class="portSection"
                    @focus="focus('port', scope.row)"
                    @blur="blur('port', scope.row)"
                    @clear="clear('port', scope.row)"
                    @input="change('port', $event, scope.row)"
                  >
                    <template #suffix>
                      <ErrorIcon />
                      <ClearableIcon />
                    </template>
                  </el-input>
                </template>
              </el-popover>
            </el-form-item>
          </el-form>
        </div>
      </template>
    </el-table-column>
    <!-- 日志类型 -->
    <el-table-column :label="traduction('ALARM_REPORT_LOG_TYPE')" class="log-type" width="400">
      <template #default="scope">
        <div v-if="!scope.row.isEdit">
          <span :id="'logType' + scope.$index">{{ scope.row.itemSelect }}</span>
        </div>
        <div v-if="scope.row.isEdit">
          <span v-for="item in scope.row.LogType" :key="item.id" class="log-type-item">
            <el-checkbox
              v-model="item.checked"
              v-addId.checkbox="item.id + scope.row.num"
              :label="$t(item.text)"
            ></el-checkbox>
          </span>
        </div>
      </template>
    </el-table-column>
    <!-- 当前状态 -->
    <el-table-column :label="traduction('ALARM_REPORT_CURRENT_STATUS')" class="status-column">
      <template #default="scope">
        <div v-if="scope.row.isEdit" class="switch">
          <el-switch id="statusValue" v-model="scope.row.statusValue"></el-switch>
        </div>
        <span
          v-if="!scope.row.isEdit"
          :class="{ statusTrue: scope.row.statusValue, statusFalse: !scope.row.statusValue }"
        >
          <span v-if="scope.row.statusValue" :id="'currentEnabled' + scope.$index">
            {{ $t('ENABLED') }}
          </span>
          <span v-if="!scope.row.statusValue" :id="'currentDisabled' + scope.$index">
            {{ $t('DISABLED') }}
          </span>
        </span>
      </template>
    </el-table-column>
    <!-- 操作 -->
    <el-table-column :label="traduction('COMMON_OPERATE')" class="operate-column">
      <template #default="scope">
        <div v-if="!scope.row.isEdit">
          <a
            :id="`edit${scope.row.num}`"
            :class="{ 'not-allow': !props.hasPermission || props.isSystemLock }"
            class="operate edit"
            @click="edit(scope.row)"
          >
            {{ $t('COMMON_EDIT') }}
          </a>
          <a
            :id="`test${scope.row.num}`"
            :class="{ 'not-allow': !props.hasPermission }"
            class="operate test"
            @click="test(scope.row)"
          >
            {{ $t('ALARM_REPORT_TEST') }}
          </a>
        </div>
        <div v-if="scope.row.isEdit">
          <a
            v-if="scope.row.canSave"
            :id="`save${scope.row.num}`"
            class="operate save"
            @click="save(scope.row)"
          >
            {{ $t('COMMON_SAVE') }}
          </a>
          <a v-else :id="`save${scope.row.num}`" class="operate save not-allow">
            {{ $t('COMMON_SAVE') }}
          </a>
          <a :id="`cancel${scope.row.num}`" class="operate cancel" @click="cancel(scope.row)">
            {{ $t('COMMON_CANCEL') }}
          </a>
        </div>
      </template>
    </el-table-column>
    <template #empty>
      <TableNoData />
    </template>
  </el-table>
</template>

<script lang="ts" setup>
import TableNoData from '@/components/TableNoData/TableNoData.vue';
import { traduction } from '@/utils/language';
import { DomainValidators } from '@/validators/domain-validators';
import { rangeVerification } from '@/validators/validation-functions';
import { ElForm } from 'element-plus';
import { nextTick, onMounted, reactive, ref, watch } from 'vue';
import ErrorIcon from '@/components/ErrorIcon/ErrorIcon.vue';
import ClearableIcon from '@/components/ClearableIcon/ClearableIcon.vue';
import { DOMAIN_NAME, IPV4, IPV6 } from '@/utils/regular';
const props = defineProps({
  data: {
    required: true,
    type: Object,
    default: () => {
      return {};
    },
  },
  isSystemLock: {
    required: true,
    type: Boolean,
  },
  hasPermission: {
    required: true,
    type: Boolean,
  },
});
const emits = defineEmits(['operateChange']);
const popoverVisible = reactive({
  serviceAddr: {},
  port: {},
});
const formRefObjs: any = reactive({});
const formRefObjsPort: any = reactive({});
const protocolType = ref('');
// 点击编辑的数据行序号
let editIndex: number = -1;
let editIndexTemp: number = -1;
function edit(row: any) {
  if (!props.hasPermission || props.isSystemLock) {
    return;
  }
  editIndex = row.num;
  editIndexTemp = row.num;
  const params = {
    key: 'edit',
    value: row,
  };
  emits('operateChange', params);
  nextTick(() => {
    formRefObjs[row.num].addr.clearValidate();
  });
}
function cancel(row: any) {
  const params = {
    key: 'cancel',
    value: row,
  };

  emits('operateChange', params);
}
function save(row: any) {
  if (row.disabled || row.port === null || row.port === '') {
    return;
  }
  const params = {
    key: 'save',
    value: row,
  };
  emits('operateChange', params);
}
function test(row: any) {
  if (!props.hasPermission) {
    return;
  }
  const params = {
    key: 'test',
    value: row,
  };
  emits('operateChange', params);
}
const formRules: any = reactive({
  serviceAddr: DomainValidators.ipv46AndDomin(),
  port: {
    trigger: 'change',
    required: true,
    type: 'number',
    isInteger: true,
    min: 1,
    max: 65535,
    message: traduction('VALIDTOR_RANGE'),
    validator: rangeVerification,
  },
});
// 表单校验结果
const validateResult = {};
function change(key: string, value: string, row: any) {
  validateResult[key] = formRules[key].validator(formRules[key], value, () => {});
}

function checkIp(value: any, callback: (error?: Error) => void) {
  if (value === '') {
    callback();
    return true;
  }
  let result = false;
  if (/^[0-9.]+$/.test(value)) {
    result = IPV4.test(value);
  } else if (value.indexOf(':') > -1) {
    result = IPV6.test(value);
  } else {
    result = DOMAIN_NAME.test(value);
  }
  !result ? callback(new Error()) : callback();
  return result;
}

function checkDomin(value: any, callback: (error?: Error) => void) {
  if (value === '') {
    callback();
    return true;
  }
  let result = false;
  if (/[0-9.]+$/.test(value)) {
    result = false;
  } else if (value.indexOf(':') > -1) {
    result = false;
  } else {
    result = DOMAIN_NAME.test(value);
  }
  !result ? callback(new Error()) : callback();
  return result;
}

// 表单校验发生时 - 控制保存按钮状态 state:校验结果
function validateAction(row: any) {
  row.canSave =
    rangeVerification(formRules.port, row.port, () => {}) && checkIp(row.serviceAddr, () => {});
  const action = (key: any, value: boolean) => {
    validateResult[key] = value;
    nextTick(() => {
      let allStae: boolean[] = [];
      validateResult['port'] = rangeVerification(
        {
          trigger: 'change',
          required: true,
          type: 'number',
          isInteger: true,
          min: 1,
          max: 65535,
          message: traduction('VALIDTOR_RANGE'),
          validator: rangeVerification,
        },
        row.port,
        () => {},
      );
      for (let item in validateResult) {
        if ({}.hasOwnProperty.call(validateResult, item)) {
          allStae.push(validateResult[item]);
        }
      }
      row.disabled = allStae.some(item => item === false);
    });
  };
  return { action };
}
function focus(key: string, row: any) {
  popoverVisible[key][row.num] = true;
}

function blur(key: string, row: any) {
  popoverVisible[key][row.num] = false;
}

function clear(key: string, row: any) {
  // 如果没有focus，那么这个地方需要手动调用一次校验
  if (popoverVisible[key] !== row.num) {
    if (key === 'port') {
      formRefObjsPort[row.num]['port'].validateField(key);
    } else {
      formRefObjs[row.num]['addr'].validateField(key);
    }
  }
}
function setAddrFormRef(el: any) {
  if (!formRefObjs[editIndexTemp]) {
    formRefObjs[editIndexTemp] = {};
  }
  if (editIndex >= 0) {
    --editIndex;
  }
  if (editIndex === 0 || editIndexTemp === -1) {
    formRefObjs[editIndexTemp]['addr'] = el;
  }
}
function setPortFormRef(el: any) {
  if (!formRefObjsPort[editIndexTemp]) {
    formRefObjsPort[editIndexTemp] = {};
  }
  formRefObjsPort[editIndexTemp]['port'] = el;
}
watch(
  () => props.data,
  val => {
    protocolType.value = val[0].type;
    formRules.serviceAddr = DomainValidators.ipv46AndDomin();
    val.map((item: any) => {
      popoverVisible.serviceAddr[item.num] = false;
      popoverVisible.port[item.num] = false;
    });
  },
);

watch(
  () => protocolType.value,
  () => {
    nextTick(() => {
      Object.keys(formRefObjsPort).forEach(item => {
        formRefObjsPort[item].port.clearValidate();
      });
      Object.keys(formRefObjs).forEach(item => {
        formRefObjs[item].addr.clearValidate();
      });
    });
  },
);
</script>

<style lang="scss" scoped>
.operate {
  cursor: pointer;
  color: var(--o-color-primary);
  &.not-allow {
    color: #b8becc !important;
    cursor: not-allowed !important;
  }
  &:hover {
    color: var(--o-color-primary-secondary);
  }
}
.portSection {
  width: 120px;
}
.edit {
  margin-right: 8px;
}
.save {
  margin-right: 8px;
}
.statusFalse {
  & > span {
    font-size: 12px;
    color: #ffffff;
    display: inline-block;
    background: var(--o-text-color-tertiary);
    border-radius: var(--i-button-border-radius);
    padding: 0 14px;
  }
}
.statusTrue {
  & > span {
    font-size: 12px;
    color: #ffffff;
    display: inline-block;
    background: var(--o-color-success);
    border-radius: 2px;
    padding: 0 14px;
  }
}
.log-type-item {
  margin-right: 18px;
}
.syslog-form {
  &.has-error {
    .el-form-item {
      margin-bottom: var(--o-form-item-gap);
    }
  }
  .el-form-item {
    margin-bottom: 0;
  }
}
.switch {
  :deep(.el-switch) {
    margin-top: -0.3em;
  }
}
</style>
<style>
#syslogTable .el-table__cell {
  vertical-align: baseline;
}
</style>
