//  Copyright (c) 2024 Huawei Technologies Co., Ltd.
//  openUBMC is licensed under Mulan PSL v2.
//  You can use this software according to the terms and conditions of the Mulan PSL v2.
//  You may obtain a copy of Mulan PSL v2 at:
//        #  http://license.coscl.org.cn/MulanPSL2
//  THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
//  EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
//  MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
//  See the Mulan PSL v2 for more details.
import { packet } from './packet';
import { VirtualMedia } from './virtualmedia';
import { Image2rep } from './image2rep';
import { packed } from './packData';
import { traduction } from '@/utils/language';
import {
  uskeyboardTable,
  JS_KEY_A,
  JS_KEY_Z,
  JS_KEY_0,
  JS_KEY_9,
  JS_KEY_SEMI,
  JS_KEY_QUOTO,
  JS_KEY_BR1,
  JS_KEY_QUOT,
  JS_KEY_FF_SEMI,
  JS_KEY_FF_PLUS,
  JS_KEY_FF_MIN,
  JS_KEY_0P,
  JS_KEY_DIVP,
  JS_KEY_OR_1
} from '@/pages/Service/Kvm/utils/keysCode';
import { capsLockState } from './sharedStates';

export class ToolBar {
  public _fixed = 1;
  public _fullscreen = 0;
  public _bootoption = 0;
  public _acceleration = 0;
  public _single = 0;
  public _record = 0;
  public _definition = 0;
  public _keyboardState = 0;
  public _floatTimer = null as any;
  public _virtualMedia;
  public _slider = null as any;
  public _defineKeyWindow = null;
  public _client;
  public _recorder = null as any;
  public _lang;
  public _keyboardlayout = 0;
  // 点击的键鼠模式
  public _mouseId = 0;
  // 记录是否响应成功,0表示未响应，1为超时，2为响应
  public _responseFlag = 0;
  public _umsInterval = null as any;
  public eltIdInputList = [
    'txt_define1',
    'txt_define2',
    'txt_define3',
    'txt_define4',
    'txt_define5',
    'txt_define6',
  ];

  constructor(client: any, ip: string, port: number, privilege: any, lang: string) {
    this._virtualMedia = new VirtualMedia(client, this, ip, port);
    this._client = client;
    this._lang = lang;
    this._WidgetInit();
    this._EventBind();
  }
  
  supportFullscreen() {
    const docElm = document.getElementById('divFullscreen');
    const el = docElm as HTMLElement & {
      mozRequestFullScreen: () => Promise<void>;
      webkitRequestFullscreen: () => Promise<void>;
      msRequestFullscreen: () => Promise<void>;
    };
    const isFullscreen =
      // W3C
      document.fullscreenElement ||
      // IE
      (document as any).msFullscreenElement ||
      // 火狐
      (document as any).mozFullScreenElement ||
      // 谷歌
      (document as any).webkitFullscreenElement ||
      false;
    return [isFullscreen, el];
  }

  _WidgetInit() {
    const self = this;

    this._slider = self._client.scope.slider;
    this._slider.changeStop = (value: number) => {
      let val = value;
      if (value < 10) {
        val = 10;
      } else if (value >= 60 && value <= 70) {
        val = 70;
      }
      const data = packed.packSetImageResolution(val);
      if (self._client._communication) {
        self._client._communication._Send(data);
      }
    };
    if (this.supportFullscreen()[1]) {
      self._client.scope.fullscreenTitle = 'REMOTE_FULL_TIP';
    } else {
      self._client.scope.fullscreenTitle = 'REMOTE_FULL_TIP_NOT_SUPPORT';
    }
  }

  _EventBind() {
    const self = this;
    const floatToolbar = document.getElementsByClassName('float-toolbar');

    for (let i = 0; i < floatToolbar.length; i++) {
      const element: HTMLElement = floatToolbar.item(i) as HTMLElement;
      element.onmouseout = () => {
        if (self._fixed === 0) {
          self._floatTimer = setTimeout(() => {
            element.style.display = 'none';
          }, 1000);
        }
      };
      element.onmouseover = () => {
        if (self._fixed === 0) {
          clearTimeout(self._floatTimer);
        }
      };
    }
    const mainMenu = document.getElementsByClassName('main-menu-item');
    for (let i = 0; i < mainMenu.length; i++) {
      const element = mainMenu.item(i) as HTMLElement;
      element.onclick = () => {
        self._MainMenuEvent(element);
        // 点击软驱按钮，查询软驱使能
        if ((element.parentElement as HTMLElement).id === 'btn_floppy') {
          self._GetFloppyState();
        }
      };
    }

    (document.getElementById('btn_float') as HTMLElement).onclick = () => {
      self._FixedEvent();
    };

    (document.getElementById('btn_fullscreen') as HTMLElement).onclick = () => {
      self._client._display.toggleFullScreen();
    };

    (document.getElementById('btn_record') as HTMLElement).onclick = () => {
      // 未激活主机不能录像
      const imgPanel = document.getElementById('active_imgs_panel') as HTMLElement;
      const computedStyle = window.getComputedStyle(imgPanel);
      const displayValue = computedStyle.display;
      if (displayValue === 'flex') {
        let confirmContent = 'KVM_RECORED_FAILED';
        self._client.scope.dialogClickOK = (): void => {};
        self._client.scope.dialogClickCancel = (): void => {};
        self._client.showMessage(confirmContent, 'kvmRecord', 'COMMON_INFORMATION', 'warning', true);
        return;
      }
      self._RecordEvent();
    };

    (document.getElementById('btn_boot') as HTMLElement).onclick = (e) => {
      // 打开启动设置按钮展开子菜单时查询系统启动项的值
      if (document.getElementById('boot_submenu')?.style?.display === 'block') {
        if (e.target.tagName.toLowerCase() === 'i') {
          this._client._communication._Send(packed.packGetBootOption());
          this._client._communication._Send(packed.packGetBootMethod());
          this._client.scope.biosText.disable = true;
        }
        (document.getElementById('bios_save') as HTMLElement).onclick = () => {
          const isObjectEqual = (obj: any) =>
            this._client.scope.biosMediaSelected.value === obj.value;
          const index = this._client.scope.biosMediaOption.findIndex(isObjectEqual);
          let cmd1 = 0; // 介质
          let cmd2 = this._client.scope.biosMethodSelected.value === 'permanent' ? 15 : 1; // 生效次数
          switch (index) {
            case 0:
            case 1:
            case 2:
            case 3:
            case 4:
            case 5:
              cmd1 = index;
              break;
            default:
              return;
          }
          let cmd = (cmd2 * 16) + cmd1;
          const data = packed.packSetBootOption(cmd);
          this._client._communication._Send(data);
          this.hideAllSubMenu();
          // 高亮显示设置的启动项
          this.setBootOption(cmd);
          this._client.scope.biosText.disable = true;
        };
      }
    };

    const powerSubmenu = (
      document.getElementById('power_submenu') as HTMLElement
    ).getElementsByTagName('li');
    for (let i = 0; i < powerSubmenu.length; i++) {
      (powerSubmenu.item(i) as HTMLElement).onclick = () => {
        self._ConfirmPowerWindow(i);
      };
    }

    const bootSubmenus = Array.from(
      (document.getElementById('boot_submenu') as HTMLElement).getElementsByTagName('li')
    );
    for (let i = 0; i < bootSubmenus.length; i++) {
      bootSubmenus[i].onclick = () => {
        if (self._client._communication._sock !== null) {
        } else {
          // kvm断开时设置启动项不生效，直接隐藏子菜单
          self.hideAllSubMenu();
        }
      };
    }
    const keyboardSubmenu = (
      document.getElementById('keyboard_submenu') as HTMLElement
    ).getElementsByTagName('li');
    for (let i = 0; i < keyboardSubmenu.length; i++) {
      (keyboardSubmenu.item(i) as HTMLElement).onclick = () => {
        self._KeyboardEvent(i);
      };
    }
    const mouseSubmenu = (
      document.getElementById('mouse_submenu') as HTMLElement
    ).getElementsByTagName('li');
    for (let i = 0; i < mouseSubmenu.length; i++) {
      (mouseSubmenu.item(i) as HTMLElement).onclick = () => {
        self._MouseEvent(i);
      };
    }
    const keyboardlayoutSubmenu = (
      document.getElementById('keyboardlayout_submenu') as HTMLElement
    ).getElementsByTagName('li');
    for (let i = 0; i < keyboardlayoutSubmenu.length; i++) {
      (keyboardlayoutSubmenu.item(i) as HTMLElement).onclick = () => {
        self._KeyboardLayoutEvent(i);
      };
    }
    const keyboardlayoutSubmenuLi = (
      document.getElementById('keyboardlayout_submenu') as HTMLElement
    ).getElementsByTagName('li');
    const li = keyboardlayoutSubmenuLi[self._keyboardlayout] as HTMLElement;
    li.classList.add('select');
    (document.getElementById('btn_help') as HTMLElement).onclick = () => {
      let localeLanguage;
      switch (this._client.scope.currnetLang) {
        case 'zh':
          localeLanguage = 'zh-cn';
          break;
        case 'en':
          localeLanguage = 'en-us';
          break;
        case 'ja':
          localeLanguage = 'jap-ja';
          break;
        case 'fr':
          localeLanguage = 'fre-fr';
          break;
        case 'ru':
          localeLanguage = 'ru-ru';
          break;
        default:
          localeLanguage = 'zh-cn';
      }
      const url =
        `${window.location.href.split('#')[0]}help/${localeLanguage}/bmc_help_0046.html`;
      const popupWin = window.open(url, '_blank');
      if (popupWin) {
        popupWin.opener = null;
      }
    };
  }

  hideAllSubMenu() {
    const subMenu = document.getElementsByClassName('sub-menu');
    for (let i = 0; i < subMenu.length; i++) {
      const submenuEl = subMenu.item(i) as HTMLElement;
      submenuEl.style.display = 'none';
    }
  }

  _MainMenuEvent(o: any) {
    const subMenus = o.parentElement.querySelectorAll('.sub-menu');
    let visible;
    for (const subMenu of subMenus) {
      if (subMenu.style.display === 'block') {
        visible = subMenu;
      }
    }
    this.hideAllSubMenu();
    if (!visible) {
      for (const subMenu of subMenus) {
        subMenu.style.display = 'block';
      }
    }
  }

  _GetFloppyState() {
    const data = packet.getFloppyState(0, this._client._security);
    this._client._communication._Send(data);
  }

  _FixedEvent() {
    this._fixed = 1 - this._fixed;
    this._client.scope.isFixed = this._fixed === 1;
  }

  fullscreenAction(flag: number) {
    const self = this;
    const body = document.getElementsByTagName('body')[0];
    const statusPanel = document.getElementById('status_panel') as HTMLElement;
    const activeImgsPanel = document.getElementById('active_imgs_panel') as HTMLElement;
    if (flag === 1) {
      self._fixed = 0;
      self._client.scope.isFixed = false;
      self._fullscreen = 1;
      body.classList.remove('content');
      statusPanel.classList.remove('status-normal');
      statusPanel.classList.add('status-full-screen');
      activeImgsPanel.classList.add('active-full-screen');
      self._client.scope.fullscreenTitle = 'REMOTE_EXIT_FULL_TIP';
      self._client.scope.iconSize = 16;
    } else {
      self._fullscreen = 0;
      body.classList.add('content');
      statusPanel.classList.remove('status-full-screen');
      activeImgsPanel.classList.remove('active-full-screen');
      statusPanel.classList.add('status-normal');
      self._client.scope.fullscreenTitle = 'REMOTE_FULL_TIP';
      self._client.scope.iconSize = 16;
      self._client.scope.isExpand = false;
    }
  }

  _PowerEvent(index: number) {
    let cmd = 0;
    switch (index) {
      case 0:
      case 1:
      case 2:
      case 3:
        cmd = index;
        break;
      case 4:
        cmd = 5;
        break;
      case 5:
        cmd = 4;
        break;
      default:
        return;
    }
    const data = packed.packPowerCtrl(cmd);
    this._client._communication._Send(data);
    this.hideAllSubMenu();
  }


  _KeyboardLayoutEvent(index: number) {
    switch (index) {
      case 0:
      case 1:
      case 2:
      case 3:
      case 4:
        this._keyboardlayout = index;
        break;
      default:
        return;
    }
    if (index !== 0) {
      (document.getElementById('btn-vir-keyboard') as HTMLElement)?.classList.add('display-none');
    } else {
      (document.getElementById('btn-vir-keyboard') as HTMLElement)?.classList.remove('display-none');
    }
    this.hideAllSubMenu();
    const keyboardlayoutSubmenuLi = Array.from(
      (document.getElementById('keyboardlayout_submenu') as HTMLElement).getElementsByTagName('li')
    );

    for (const li of keyboardlayoutSubmenuLi) {
      li.classList.remove('select');
    }

    keyboardlayoutSubmenuLi[index].classList.add('select');
  }

  _KeyboardEvent(index: number) {
    switch (index) {
      case 0:
        this._client._keyboard.sendAltTab();
        break;
      case 1:
        this._client._keyboard.sendCtrlEsc();
        break;
      case 2:
        this._client._keyboard.sendCtrlShift();
        break;
      case 3:
        this._client._keyboard.sendCtrlSpace();
        break;
      case 4:
        this._client._keyboard.sendCtrlAltDel();
        break;
      case 5:
        this._ShowDefineKeyWindow();
        break;
      default:
        return;
    }
    this.hideAllSubMenu();
  }

  _MouseEvent(index: number) {
    const self = this;
    self.hideAllSubMenu();

    if (index === 3) {
      self.setKeyCapsSync();
      return;
    }

    // 防止多次点击时flag出错
    if (self._umsInterval) {
      clearInterval(self._umsInterval);
    }

    self._mouseId = index;
    let data = null;
    // 默认为未响应状态
    self._responseFlag = 0;

    // 1s内无响应自动下发键鼠模式设置
    self._umsInterval = setInterval(() => {
      // 未响应
      if (self._responseFlag !== 2) {
        // 响应状态为超时
        self._responseFlag = 1;
        self._SetMouseMode();
      }
      clearInterval(self._umsInterval);
    }, 1000);
  }

  _ShowDialog(data: any) {
    const self = this;
    if (self._responseFlag === 1) {
      // 请求超时响应，不做任何处理
      return;
    }
    self._responseFlag = 2;
    // 显示键鼠模式修改提示
    let flag = 0;
    if (self._client._security.isKvmEncryption()) {
      const temp = self._client._security.kvmDecrypt(data);
      flag = (temp[1] * 256) + temp[0];
    } else {
      flag = (data[1] * 256) + data[0];
    }
    if (flag === 1) {
      self._client.scope.dialogClickOK = () => {
        self._SetMouseMode();
      };

      self._client.scope.dialogClickCancel = () => {
        self.hideAllSubMenu();
      };
      self._client.showMessage('MOUSE_MODE_SET_TIP', 'mouseMode', 'COMMON_CONFIRM');
    } else if (flag === 0) {
      self._SetMouseMode();
    }
  }

  _SetMouseMode() {
    let data = null;
    const index = this._mouseId;
    if (index === 0) {
      data = packed.packSetMouseMode(1 - this._acceleration);
      this._client._communication._Send(data);
    } else if (index === 1) {
      this._single = 1 - this._single;
      this._client._display.switchCursor(this._single);
      const mouseSubmenuLi = (
        document.getElementById('mouse_submenu') as HTMLElement
      ).getElementsByTagName('li');
      if (this._single) {
        data = packed.packSetMouseMode(0);
        mouseSubmenuLi[1].classList.add('select');
      } else {
        data = packed.packSetMouseMode(1);
        mouseSubmenuLi[1].classList.remove('select');
      }
      this._client._communication._Send(data);
    } else if (index === 2) {
      data = packed.packResetUsb();
      this._client._communication._Send(data);
    }
  }

  _RecordEvent() {
    if (this._record === 0 && this._recorder === null) {
      this._recorder = new Image2rep();
      this._recorder.startRecord();
      this._record = 1;
      this._client.scope.isRecording = true;
      const data = packed.packStartRecord();
      this._client._communication._Send(data);
    } else if (this._record === 1 && this._recorder !== null) {
      this._recorder.stopRecord(this._client._communication._host);
      this._recorder = null;
      this._record = 0;
      this._client.scope.isRecording = false;
      const data = packed.packEndRecord();
      this._client._communication._Send(data);
    }
  }

  setBootOption(option: number) {
    let index = 0;
    switch (option) {
      case 0:
      case 1:
      case 2:
      case 3:
      case 4:
      case 5:
        index = option;
        break;
      default:
        return;
    }

    // 设置介质选项和生效方式
    this._client.scope.biosMediaSelected.value = this._client.scope.biosMediaOption[index].value;
    this._client.scope.biosMediaOriginal.value = this._client.scope.biosMediaOption[index].value;
  }

  //  后端返回1, 代表单次, 后端返回15, 代表永久, 其余默认代表单次
  setBootMethod(option: number) {
    this._client.scope.biosMethodSelected.value = option === 15 ? 'permanent' : 'single';
    this._client.scope.biosMethodOriginal.value = option === 15 ? 'permanent' : 'single';
  }

  _confirmImgWindow(hostId: number): void {
    const self = this;
    let confirmContent = 'WEB_COMFRIM_CONTEXT';
    self._client.scope.dialogClickOK = (): void => {
      if (self._client._communication) {
        self._client._communication._Send(packed.packGetActiveHosts(hostId));
      }
    };
    self._client.scope.dialogClickCancel = (): void => {};
    self._client.showMessage(confirmContent, 'kvmImg', 'COMMON_CONFIRM');
  }

  stopHostRecord(): void {
    if (this._record === 1 && this._recorder !== null) {
      this._recorder?.stopRecord(this._client._communication._host);
      this._recorder = null;
      this._record = 0;
      this._client.scope.isRecording = false;
      const data = packed.packEndRecord();
      this._client._communication._Send(data);
    }
  }

  // 激活图像/主机ID更新
  setHostInfo(status: string, hostId: number) {
    const self = this;
    let imgPanel = document.getElementById('active_imgs_panel') as HTMLElement;
    const hostName = document.getElementById('host_name') as HTMLElement;
    hostName.innerText = `${traduction('HOME_KVM_HOST').replace('num', String(hostId))}`;
    const innerDiv = imgPanel.querySelector('.active-img') as HTMLElement;
    const imgHostDiv = imgPanel.querySelector('.active-img-host') as HTMLElement;
    const imgHostBtn = document.getElementById('img_host_btn') as HTMLElement;
    const innerHostText = imgHostBtn.querySelector('.img-host-btn-text') as HTMLElement;
    if (status === 'active') {
      imgPanel.style.display = 'none';
      innerDiv.id = 'active_img_div';
      imgHostDiv.id = 'active_img_host_name';
      innerHostText.id = 'active_img_host_btn_text';
    } else {
      imgPanel.style.display = 'flex';
      innerDiv.id = 'idle_img_div';
      imgHostDiv.id = 'idle_img_host_name';
      innerHostText.id = 'idle_img_host_btn_text';
      // 主机1激活图像后, 主机2停止录像
      self.stopHostRecord();
      // 绑定激活图像事件
      imgHostBtn.onclick = () => {
        self._confirmImgWindow(hostId);
      };
    }
  }

  setMouseAcceleration(status: number) {
    this._acceleration = status;
    const mouseSubmenuLi = Array.from(
      (document.getElementById('mouse_submenu') as HTMLElement).getElementsByTagName('li')
    );
    // status为0代表单鼠标状态，1为双鼠标
    if (status) {
      mouseSubmenuLi[0].classList.add('select');
      mouseSubmenuLi[1].classList.remove('select');
      this._client._display.switchCursor(0);
      this._single = 0;
    } else {
      mouseSubmenuLi[0].classList.remove('select');
      mouseSubmenuLi[1].classList.add('select');
    }
  }

  setKeyCapsSync(): void {
    const mouseSubmenuLi = Array.from(
      (document.getElementById('mouse_submenu') as HTMLElement).getElementsByTagName('li')
    );
    if (this._client.scope.kvmParams.capsSync === '0') {
      this._client.scope.kvmParams.capsSync = '1';
      mouseSubmenuLi[3].classList.add('select');
    } else {
      this._client.scope.kvmParams.capsSync = '0';
      mouseSubmenuLi[3].classList.remove('select');
    }
  }

  setFloppyState(data: any) {
    let floppyState = 1;
    if (data.length > 1) {
      if (this._client._security.isKvmEncryption()) {
        const temp = this._client._security.kvmDecrypt(data);
        floppyState = (temp[1] * 256) + temp[0];
      } else {
        floppyState = (data[1] * 256) + data[0];
      }
    } else {
      floppyState = data[0];
    }
    // 控制禁用提示显示
    this._client.scope.floppyState = floppyState;

    const floppyTable = document.getElementById('floppy_submenu') as HTMLElement;
    // floppyState为0时，软驱功能禁用
    if (floppyState === 0) {
      floppyTable.style.display = 'none';
    } else {
      floppyTable.style.display = 'block';
    }
  }

  setKeyboardLight(status: number) {
    this._keyboardState = status;
    capsLockState.value = !!(status & 0x02);
  }

  setDefinition(status: number) {
    const current = this._slider.value;
    if (
      status < 10 ||
      status > 100 ||
      (current >= status && current < status + 10) ||
      (status === 10 && current <= 10)
    ) {
      return;
    }
    this._slider.value = status;
  }

  _ShowDefineKeyWindow() {
    const self = this;
    self._client._communication._Send(packed.packGetCustom());
    self._client.scope.dialogClickOK = () => {
      const txtDefine1 = document.getElementById('txt_define1') as HTMLElement;
      const txtDefine2 = document.getElementById('txt_define2') as HTMLElement;
      const txtDefine3 = document.getElementById('txt_define3') as HTMLElement;
      const txtDefine4 = document.getElementById('txt_define4') as HTMLElement;
      const txtDefine5 = document.getElementById('txt_define5') as HTMLElement;
      const txtDefine6 = document.getElementById('txt_define6') as HTMLElement;
      self._client._keyboard.sendSelfDef(
        txtDefine1.getAttribute('keyCode'),
        txtDefine1.getAttribute('key'),
        txtDefine2.getAttribute('keyCode'),
        txtDefine2.getAttribute('key'),
        txtDefine3.getAttribute('keyCode'),
        txtDefine3.getAttribute('key'),
        txtDefine4.getAttribute('keyCode'),
        txtDefine4.getAttribute('key'),
        txtDefine5.getAttribute('keyCode'),
        txtDefine5.getAttribute('key'),
        txtDefine6.getAttribute('keyCode'),
        txtDefine6.getAttribute('key')
      );
    };

    self._client.scope.dialogClickCustom = (keyArr: any[], keyCodeArr: any[]): void => {
      self._client._keyboard.sendSelfDef(
        keyCodeArr[0],
        keyArr[0],
        keyCodeArr[1],
        keyArr[1],
        keyCodeArr[2],
        keyArr[2],
        keyCodeArr[3],
        keyArr[3],
        keyCodeArr[4],
        keyArr[4],
        keyCodeArr[5],
        keyArr[5]
      );
    };

    self._client.scope.dialogClickSave = (): void => {
      const txtDefine1 = document.getElementById('txt_define1') as HTMLElement;
      const txtDefine2 = document.getElementById('txt_define2') as HTMLElement;
      const txtDefine3 = document.getElementById('txt_define3') as HTMLElement;
      const txtDefine4 = document.getElementById('txt_define4') as HTMLElement;
      const txtDefine5 = document.getElementById('txt_define5') as HTMLElement;
      const txtDefine6 = document.getElementById('txt_define6') as HTMLElement;
      self._client._keyboard.saveSendSelfDef(
        txtDefine1.getAttribute('keyCode'),
        txtDefine1.getAttribute('key'),
        txtDefine2.getAttribute('keyCode'),
        txtDefine2.getAttribute('key'),
        txtDefine3.getAttribute('keyCode'),
        txtDefine3.getAttribute('key'),
        txtDefine4.getAttribute('keyCode'),
        txtDefine4.getAttribute('key'),
        txtDefine5.getAttribute('keyCode'),
        txtDefine5.getAttribute('key'),
        txtDefine6.getAttribute('keyCode'),
        txtDefine6.getAttribute('key'),
        'save'
      );
    };
    self._client.scope.dialogClickDel = (keyArr: any[], keyCodeArr: any[]): void => {
      self._client._keyboard.saveSendSelfDef(
        keyCodeArr[0],
        keyArr[0],
        keyCodeArr[1],
        keyArr[1],
        keyCodeArr[2],
        keyArr[2],
        keyCodeArr[3],
        keyArr[3],
        keyCodeArr[4],
        keyArr[4],
        keyCodeArr[5],
        keyArr[5],
        'delete'
      );
    };

    self._client.scope.dialogClickCancel = () => {};
    self._client.showMessage('', 'keyboard', 'HOME_SELF_DEFINE');
  }

  _ConfirmPowerWindow(obj: any) {
    const self = this;
    let confirmContent = null;
    switch (obj) {
      case 0:
        confirmContent = 'WEB_COMFRIM_CONTEXT';
        break;
      case 1:
        confirmContent = 'STRONG_DOWN_POWER_TIP';
        break;
      case 2:
        confirmContent = 'WEB_COMFRIM_CONTEXT';
        break;
      case 3:
        confirmContent = 'POWER_REST_START_TIP';
        break;
      case 4:
        confirmContent = 'POWER_SAFE_LABLE_TIP';
        break;
      case 5:
        confirmContent = 'POWER_OFF_POWER_ON_TIP';
        break;
      default:
        confirmContent = 'WEB_COMFRIM_CONTEXT';
        return;
    }

    self._client.scope.dialogClickOK = () => {
      self._PowerEvent(obj);
    };

    self._client.scope.dialogClickCancel = () => {};
    self._client.showMessage(confirmContent, 'kvmPower', 'COMMON_CONFIRM');
  }

  setDefineKey(e: any) {
    const target = e.srcElement || e.originalTarget;
    const eltId = target.id;
    let keysym;
    const eltIdList = [
      'Meta_91',
      'Alt_18',
      'Delete_46',
      'Control_17',
      'ScrollLock_145',
      'PrintScreen_44',
      'Insert_45',
      'AltGraph_18',
      'Meta_92',
      'Control_17_Right',
    ];
    keysym = this._GetKey(e);

    if (this.eltIdInputList.includes(eltId) && keysym !== 'Unknow') {
      this._client.scope.canSave = true;
      const input = document.getElementById(eltId) as HTMLInputElement;
      input.value = keysym;
      if (keysym === ' ') {
        input.value = 'Space';
      }
      if (Number(e.keyCode) === 91) {
        keysym = 'LMeta';
        input.value = 'LMeta';
      }
      if (Number(e.keyCode) === 92) {
        keysym = 'RMeta';
        input.value = 'RMeta';
      }
      (document.getElementById(eltId) as HTMLElement).setAttribute('key', keysym);
      (document.getElementById(eltId) as HTMLElement).setAttribute(
        'keyCode',
        e.keyCode || e.which || e.charCode
      );
    }

    if (eltIdList.includes(eltId)) {
      this._client.scope.canSave = true;
      this.btnInput(e);
    }
  }


  btnInput(e: any): void {
    const target = e.srcElement || e.originalTarget;
    const eltId = target.id;
    e.key = eltId.split('_')[0];
    e.keyCode = eltId.split('_')[1];
    let input = document.getElementById('txt_define1') as HTMLInputElement;
    for (let i = 1; i <= this.eltIdInputList.length; i++) {
      input = document.getElementById(`txt_define${i}`) as HTMLInputElement;
      if (!input.value) {
        break;
      }
    }
    input.value = eltId.split('_')[0];
    (document.getElementById(input.id) as HTMLElement).setAttribute('key', this._GetKey(e));
    if (Number(e.keyCode) === 91) {
      (document.getElementById(input.id) as HTMLElement).setAttribute('key', 'LMeta');
      input.value = 'LMeta';
    }
    if (Number(e.keyCode) === 92) {
      (document.getElementById(input.id) as HTMLElement).setAttribute('key', 'RMeta');
      input.value = 'RMeta';
    }
    (document.getElementById(input.id) as HTMLElement).setAttribute('keyCode', eltId.split('_')[1]);
  }

  _GetKey(e: any): any {
    const keyLocation = Number(e.location || e.keyLocation);
    const condition = typeof e.key !== 'undefined' && e.key !== 'MozPrintableKey' && e.key !== 'Alt' && keyLocation !== 2;
    const keyIsAlt = e.key !== 'MozPrintableKey' && e.key === 'Alt' && keyLocation === 2;
    if (condition) {
      return e.key;
    } else if (keyIsAlt || e.key === 'AltGraph') {
      // 意大利键盘模式下，按下右边Alt键，组合键输入框内应显示为"AltGraph"
      return 'AltGraph';
    } else {
      return this._GetKeysym(e);
    }
  }

  _GetKeysym(e: any): any {
    const keyCode = Number(e.keyCode || e.which || e.charCode);
    for (const uskeyboard of uskeyboardTable) {
      if (uskeyboard[0] === keyCode) {
        if (
          (keyCode >= JS_KEY_A && keyCode <= JS_KEY_Z) ||
          (keyCode >= JS_KEY_0 && keyCode <= JS_KEY_9) ||
          (keyCode >= JS_KEY_SEMI && keyCode <= JS_KEY_QUOTO) ||
          (keyCode >= JS_KEY_BR1 && keyCode <= JS_KEY_QUOT) ||
          keyCode === JS_KEY_FF_SEMI ||
          keyCode === JS_KEY_FF_PLUS ||
          keyCode === JS_KEY_FF_MIN
        ) {
          return e.shiftKey ? uskeyboard[4] : uskeyboard[3];
        } else if ((keyCode >= JS_KEY_0P && keyCode <= JS_KEY_DIVP) || keyCode === JS_KEY_OR_1) {
          return uskeyboard[3];
        } else {
          return uskeyboard[2];
        }
      }
    }
    return 'Unknow';
  }

  _CustomErrData(data: any, type: string): void {
    const self = this;
    self._client.scope.tip = `${type}_${data[0]}`;
  }

  _CustomData(data: any): void {
    const self = this;
    let arr = [] as any[];
    if (data.length > 0) {
      arr = this._DealCustomData(data);
      for (let i = 0; i < arr.length; i++) {
        arr[i] = this._DealPerCustomData(arr[i]);
      }
      for (let i = 0; i < arr.length; i++) {
        for (let j = 0; j < arr[i].length; j++) {
          arr[i][j] = [arr[i][j][0], self._client._keyboard.decodeUtf8(arr[i][j])];
        }
      }
    }
    self._client.scope.customData = this._GetFinalData(arr);
  }

  _GetFinalData(data: any[]): any[] {
    let arr = [] as any[];
    for (let dataItem of data) {
      let value = [];
      let label = [];
      for (let item of dataItem) {
        if (item[1] === ' ') {
          item[1] = 'Space';
        }
        if (Number(item[0]) === 91) {
          item[1] = 'LMeta';
        }
        if (Number(item[0]) === 92) {
          item[1] = 'RMeta';
        }
        label.push(item[1]);
        value.push(item[0]);
      }
      arr.push({
        value: value.join('+'),
        label: label.join('+'),
      });
    }
    return arr;
  }

  _DealCustomData(data: any): any[] {
    let arr = [] as any[];
    let flag = 0;
    let temp = -1;
    for (let i = 0; i < data.length; i++) {
      if (flag === i) {
        flag += data[i] + 1;
        ++temp;
        arr[temp] = [];
      } else {
        arr[temp].push(data[i]);
      }
    }
    return arr;
  }

  _DealPerCustomData(data: any): any[] {
    let arr = [] as any[];
    let flag = 1;
    let temp = -1;
    for (let i = 0; i < data.length; i++) {
      if (flag - 1 === i) {
        ++temp;
        arr[temp] = [];
      }
      if (flag === i) {
        flag += data[i] + 2;
      } else {
        arr[temp].push(data[i]);
      }
    }
    return arr;
  }
}


