//  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 { UdfImageBuilder } from './udfImageBuilder';
import { SCSIProcessor } from './scsiProcessor';
import { packed } from './packData';
import { packVmm } from './packVmmData';
import { VmmCmdType } from '@/model/base-enum';
export class VirtualMedia {
  public _ip = null as any;
  public _port = null as any;
  public _socket = null as any;
  public _state = null as any;
  public _timeout = 0;
  public _monitorTimer = null as any;
  public _disconnectSet = 0;
  public _connectingSet = 0;
  public _openDeviceSet = 0;
  public _establishedSet = 0;
  public _toolbar = null as any;
  public _client = null as any;
  public _ufiProcessor = null as any;
  public _sffProcessor = null as any;
  public _needReconnectCdrom = false;
  public _needReconnectFloppy = false;
  public _cdromImage = null as any;
  public _cdromDirectory = null as any;
  public _cdromConnect = null as any;
  public _cdromInsert = null as any;
  public _cdromFolders = null as any;
  public _floppyImage = null as any;
  public _floppyConnect = null as any;
  public _floppyInsert = null as any;
  public _udfTimer = null as any;
  public _udfBuilder = null as any;
  public _securityWarning = 1;
  public _cdromImageFile = null as any;
  public _cdromDirectoryFile = null as any;
  public _cdromDirectoryFolders = [] as any;
  public _floppyImageFile = null as any;
  public _isSffInit = false;
  public _sffData = null as any;

  public ACK = 0;
  public REGISTER = 1;
  public CREATE = 2;
  public TRANS_UFI = 3;
  public TRANS_SFF = 4;
  public CLOSE_VM = 5;
  public HEART = 6;
  public CLOSE_DEV = 7;
  public UFI_END = 0xfe;
  public SFF_END = 0xff;

  public PROTOCOL_SFF = 0;
  public PROTOCOL_UFI = 1;

  public STATE_INIT = 0;
  public STATE_STATE_REQUEST = 1;
  public STATE_STATE_RESPONSE = 2;
  public STATE_PORT_REQUEST = 3;
  public STATE_PORT_RESPONSE = 4;
  public STATE_CONNECTING = 5;
  public STATE_CONNECTED = 6;
  public STATE_AUTHORING = 7;
  public STATE_ESTABLISHED = 8;
  public STATE_ERROR = 9;

  public CDROM_IMAGE_LINK = 1;
  public CDROM_DIRECTORY_LINK = 2;
  public FLOPPY_IMAGE_LINK = 4;

  public ACK_AUTH_OK = 0x00;
  public ACK_INTERNAL_ERROR = 0x01;
  public ACK_DEVICE_CREATED = 0x10;
  public ACK_DEVICE_FAIL = 0x11;
  public ACK_VM_BUSY = 0x31;
  public ACK_AUTH_FAIL = 0x32;
  public _sock = null as any;
  constructor(client: any, toolbar: any, ip: string, port: number) {
    this._ip = ip;
    this._port = port;
    this._state = this.STATE_INIT;
    this._toolbar = toolbar;
    this._client = client;
    this._WidgetInit();
    this._EventBind();
  }
  
  _WaitUDFReady() {
    if (this._udfBuilder == null) {
      this._udfBuilder = new UdfImageBuilder();
      let file = null;
      let fileName = 'UDF-Disc';
      if (this._cdromDirectoryFolders?.length > 0) {
        file = this._cdromDirectoryFolders;
        let fName = this._client.scope.locationFolders.uploaderConfig.foldersName;
        fileName = fName.length > 29 ? `${fName.substring(0, 29)}~` : fName;
      } else {
        file = [this._cdromDirectoryFile];
      }
      this._udfBuilder.setSourceFiles(file);
      this._udfBuilder.setImageIdentifier(fileName);
      this._udfBuilder.execute();
    } else if (this._udfBuilder.isISOReady()) {
      clearInterval(this._udfTimer);
      if (this._establishedSet & this.CDROM_DIRECTORY_LINK) {
        this._cdromDirectory.uploaderConfig.disabled = false;
        this._cdromFolders.uploaderConfig.disabled = false;
        this._cdromConnect.disable = false;
        this._cdromInsert.disable = false;
      } else {
        this._cdromDirectory.uploaderConfig.disabled = false;
        this._cdromFolders.uploaderConfig.disabled = false;
        this._cdromConnect.disable = false;
        this._cdromInsert.disable = true;
        this._client.scope.cdDvd[0].disable = false;
        this._client.scope.cdDvd[1].disable = false;
        this._client.scope.cdDvd[2].disable = false;
      }
    }
  }

  _WidgetInit() {
    const self = this;
    this._cdromImage = this._client.scope.isoCdrom;
    this._cdromDirectory = this._client.scope.locationFile;
    this._cdromConnect = this._client.scope._cdromConnect;
    this._cdromInsert = this._client.scope._cdromInsert;
    this._floppyImage = this._client.scope.isoFloppy;
    this._floppyConnect = this._client.scope._floppyConnect;
    this._floppyInsert = this._client.scope._floppyInsert;
    this._cdromFolders = this._client.scope.locationFolders;
    this._cdromImage.uploaderConfig.onAddItemSuccess = (fileItem: any) => {
      fileItem.mouseenter = function () {
        if (this.disable) {
          return;
        }
        this.isHover = !0;
      };
      self._cdromImageFile = fileItem.raw;
      if (self._establishedSet & self.CDROM_IMAGE_LINK) {
        self._cdromConnect.disable = false;
        self._cdromInsert.disable = false;
      } else {
        self._cdromConnect.disable = false;
        self._cdromInsert.disable = true;
      }
    };

    this._cdromDirectory.uploaderConfig.onAddItemSuccess = (fileItem: any) => {
      fileItem.mouseenter = function () {
        if (this.disable) {
          return;
        }
        this.isHover = !0;
      };
      self._cdromDirectoryFile = fileItem.raw;
      self._udfBuilder = null;
      self._cdromDirectory.uploaderConfig.disabled = true;
      self._cdromConnect.disable = true;
      self._cdromInsert.disable = true;
      self._client.scope.cdDvd[0].disable = true;
      self._client.scope.cdDvd[1].disable = true;
      self._client.scope.cdDvd[2].disable = true;
      self._udfTimer = setInterval(() => {
        self._WaitUDFReady();
      }, 500);
    };

    this._floppyImage.uploaderConfig.onAddItemSuccess = (fileItem: any) => {
      fileItem.mouseenter = function () {
        if (this.disable) {
          return;
        }
        this.isHover = !0;
      };
      self._floppyImageFile = fileItem.raw;
      if (fileItem.size !== 0x200 * 0x0b40) {
        if (self._establishedSet & self.FLOPPY_IMAGE_LINK) {
          self._floppyConnect.disable = false;
        } else {
          self._floppyConnect.disable = true;
        }
        self._floppyInsert.disable = true;
        self._client.showMessage('REMOTE_ERR_FLOPPY_FORMAT', 'floppyFormatDialog');
      } else {
        if (self._establishedSet & self.FLOPPY_IMAGE_LINK) {
          self._floppyConnect.disable = false;
          self._floppyInsert.disable = false;
        } else {
          self._floppyConnect.disable = false;
          self._floppyInsert.disable = true;
        }
      }
    };
    this._cdromFolders.uploaderConfig.onAddItemSuccess = (fileItem: any) => {
      fileItem.mouseenter = function () {
        if (this.disable) {
          return;
        }
        this.isHover = !0;
      };
      self._cdromDirectoryFolders.splice(0);
      for (let i = 0; i < fileItem.length; i++) {
        let fileRaw = fileItem[i];
        self._cdromDirectoryFolders.push(fileRaw);
      }
      self._udfBuilder = null;
      self._cdromFolders.uploaderConfig.disabled = true;
      self._cdromConnect.disable = true;
      self._cdromInsert.disable = true;
      self._client.scope.cdDvd[0].disable = true;
      self._client.scope.cdDvd[1].disable = true;
      self._client.scope.cdDvd[2].disable = true;
      self._udfTimer = setInterval(() => {
        self._WaitUDFReady();
      }, 500);
    };
  }

  _EventBind() {
    const self = this;
    self._client.scope.rChange = () => {
      self._client.scope.locationFolders.showErrorTip = false;
      self._cdromConnect.disable = true;
      self._cdromInsert.disable = true;
      self._cdromDirectoryFile = null;
      self._cdromImageFile = null;
      self._cdromDirectoryFolders.splice(0);
      self._client.scope.locationFolders.uploaderConfig.foldersName = '';
      // 切换光驱选择文件类型
      if (self._client.scope.cdDvdSelected.value === 'iso') {
        self._client.scope.isoCdrom.uploaderConfig.disabled = false;
        self._client.scope.locationFile.uploaderConfig.disabled = true;
        self._client.scope.locationFolders.uploaderConfig.disabled = true;
        if (self._cdromImageFile !== null) {
          self._cdromConnect.disable = false;
          self._cdromInsert.disable = true;
        } else {
          self._cdromConnect.disable = true;
          self._cdromInsert.disable = true;
        }
      } else if (self._client.scope.cdDvdSelected.value === 'location') {
        self._client.scope.isoCdrom.uploaderConfig.disabled = true;
        self._client.scope.locationFile.uploaderConfig.disabled = false;
        self._client.scope.locationFolders.uploaderConfig.disabled = true;
        if (self._cdromDirectoryFile !== null) {
          self._cdromConnect.disable = false;
          self._cdromInsert.disable = true;
        } else {
          self._cdromConnect.disable = true;
          self._cdromInsert.disable = true;
        }
      } else {
        self._client.scope.isoCdrom.uploaderConfig.disabled = true;
        self._client.scope.locationFile.uploaderConfig.disabled = true;
        self._client.scope.locationFolders.uploaderConfig.disabled = false;
        if (self._cdromDirectoryFolders?.length > 0) {
          self._cdromConnect.disable = false;
          self._cdromInsert.disable = true;
        } else {
          self._cdromConnect.disable = true;
          self._cdromInsert.disable = true;
        }
      }
    };
    this._cdromConnect.click = () => {
      const flag =
        self._client.scope.cdDvdSelected.value === 'iso'
          ? self.CDROM_IMAGE_LINK
          : self.CDROM_DIRECTORY_LINK;
      if (
        self._establishedSet & self.CDROM_IMAGE_LINK ||
        self._establishedSet & self.CDROM_DIRECTORY_LINK
      ) {
        self._disconnectSet = self._disconnectSet | flag;
        self._needReconnectCdrom = false;
        if (self._monitorTimer == null) {
          self._monitorTimer = setInterval(() => {
            self._VMMLinkMonitor();
          }, 1000);
        }
      } else {
        self._cdromImage.uploaderConfig.disabled = true;
        self._cdromDirectory.uploaderConfig.disabled = true;
        self._cdromFolders.uploaderConfig.disabled = true;
        self._cdromConnect.disable = true;
        self._cdromInsert.disable = true;
        self._client.scope.cdDvd[0].disable = true;
        self._client.scope.cdDvd[1].disable = true;
        self._client.scope.cdDvd[2].disable = true;
        self._connectingSet = self._connectingSet | flag;
        if (self._monitorTimer == null) {
          self._monitorTimer = setInterval(() => {
            self._VMMLinkMonitor();
          }, 1000);
        }
      }
    };
    this._cdromInsert.click = () => {
      self._cdromConnect.disable = true;
      self._cdromInsert.disable = true;
      if (self._sffProcessor._device.isEject() && self._cdromInsert.text === 'REMOTE_INSERT') {
        if (self._client.scope.cdDvdSelected.value === 'iso') {
          self._sffProcessor._device._Init(self._cdromImageFile);
          self._cdromImage.uploaderConfig.disabled = true;
        } else {
          self._sffProcessor._device._Init(self._udfBuilder.fileBlob);
          self._cdromDirectory.uploaderConfig.disabled = true;
          self._cdromFolders.uploaderConfig.disabled = true;
        }
        setTimeout(() => {
          self._cdromInsert.text = 'REMOTE_EJECT';
          self._cdromConnect.disable = false;
          self._cdromInsert.disable = false;
        }, 3000);
      } else {
        self._sffProcessor._device._Init(null);
        setTimeout(() => {
          if (self._client.scope.cdDvdSelected.value === 'iso') {
            self._cdromImage.uploaderConfig.disabled = false;
          } else {
            self._cdromDirectory.uploaderConfig.disabled = false;
            self._cdromFolders.uploaderConfig.disabled = false;
          }
          self._cdromInsert.text = 'REMOTE_INSERT';
          self._cdromConnect.disable = false;
          self._cdromInsert.disable = false;
        }, 3000);
      }
    };
    this._floppyConnect.click = () => {
      if (self._establishedSet & self.FLOPPY_IMAGE_LINK) {
        self._disconnectSet = self._disconnectSet | self.FLOPPY_IMAGE_LINK;
        self._needReconnectFloppy = false;
        if (self._monitorTimer == null) {
          self._monitorTimer = setInterval(() => {
            self._VMMLinkMonitor();
          }, 1000);
        }
      } else {
        self._floppyImage.uploaderConfig.disabled = true;
        self._floppyConnect.disable = true;
        self._floppyInsert.disable = true;
        self._connectingSet = self._connectingSet | self.FLOPPY_IMAGE_LINK;
        if (self._monitorTimer == null) {
          self._monitorTimer = setInterval(() => {
            self._VMMLinkMonitor();
          }, 1000);
        }
      }
    };
    this._floppyInsert.click = () => {
      self._floppyConnect.disable = true;
      self._floppyInsert.disable = true;
      if (self._ufiProcessor._device.isEject() && self._floppyInsert.text === 'REMOTE_INSERT') {
        self._ufiProcessor._device._Init(self._floppyImageFile);
        self._floppyImage.uploaderConfig.disabled = true;
        setTimeout(() => {
          self._floppyInsert.text = 'REMOTE_EJECT';
          self._floppyConnect.disable = false;
          self._floppyInsert.disable = false;
        }, 3000);
      } else {
        self._ufiProcessor._device._Init(null);
        setTimeout(() => {
          self._floppyImage.uploaderConfig.disabled = false;
          self._floppyInsert.text = 'REMOTE_INSERT';
          self._floppyConnect.disable = false;
          self._floppyInsert.disable = false;
        }, 3000);
      }
    };
  }

  // 发送vmm使能状态请求
  _SendStateRequest() {
    const data = packed.packGetVmmEnable();
    this._client._communication._Send(data);
    this._timeout = 0;
    this._state++;
  }

  _SendPortRequest() {
    const data = packed.packGetVmmPort();
    this._client._communication._Send(data);
    this._timeout = 0;
    this._state++;
  }

  _CreateConnection() {
    const self = this;
    this._sock = new WebSocket(`wss://${this._ip}:${this._port}/websocket/vmm`);
    this._sock.binaryType = 'arraybuffer';
    this._sock.onopen = (e: any) => {
      self._WSOpen(e);
    };
    this._sock.onclose = (e: any) => {
      self._WSClose(e);
    };
    this._sock.onerror = (e: any) => {
      self._WSError(e);
    };
    this._sock.onmessage = (e: any) => {
      self._WSMessage(e);
    };
    this._timeout = 0;
    if (this._state === this.STATE_PORT_RESPONSE) {
      this._state++;
    }
  }

  _AuthConnection() {
    const kvmToken = this._client._communication.getKvmToken();
    const pack = packVmm.packConnect(kvmToken);
    this._Send(pack);
    this._timeout = 0;
    this._state++;
  }

  _SendHeartBeat() {
    if (this._timeout >= 5) {
      const data = packVmm.packHeartBeat();
      this._Send(data);
    }
  }

  _OpenDevice() {
    let pack = packVmm.packCreateVirtualDev();
    if ((this._connectingSet & this.CDROM_IMAGE_LINK) === this.CDROM_IMAGE_LINK) {
      this._connectingSet = this._connectingSet & 0xfe;
      this._openDeviceSet = this._openDeviceSet | this.CDROM_IMAGE_LINK;
      this._Send(pack);
    } else if ((this._connectingSet & this.CDROM_DIRECTORY_LINK) === this.CDROM_DIRECTORY_LINK) {
      this._connectingSet = this._connectingSet & 0xfd;
      this._openDeviceSet = this._openDeviceSet | this.CDROM_DIRECTORY_LINK;
      this._Send(pack);
    } else if ((this._connectingSet & this.FLOPPY_IMAGE_LINK) === this.FLOPPY_IMAGE_LINK) {
      this._connectingSet = this._connectingSet & 0xfb;
      this._openDeviceSet = this._openDeviceSet | this.FLOPPY_IMAGE_LINK;
      const pack3 = new Uint8Array(12);
      pack3[0] = this.CREATE;
      pack3[1] = 1;
    }
  }

  _CloseDevice() {
    let pack = packVmm.packDISCVirtualDev();
    if (
      this._disconnectSet & this.CDROM_IMAGE_LINK &&
      this._establishedSet & this.CDROM_IMAGE_LINK
    ) {
      this._disconnectSet = this._disconnectSet & 0xfe;
      this._establishedSet = this._establishedSet & 0xfe;
      this._sffProcessor = null;
      if (this._establishedSet === 0) {
        this._Reset();
      } else {
        this._Send(pack);
        this._ResetCDROM();
      }
    } else if (
      this._disconnectSet & this.CDROM_DIRECTORY_LINK &&
      this._establishedSet & this.CDROM_DIRECTORY_LINK
    ) {
      this._disconnectSet = this._disconnectSet & 0xfd;
      this._establishedSet = this._establishedSet & 0xfd;
      this._sffProcessor = null;
      if (this._establishedSet === 0) {
        this._Reset();
      } else {
        this._Send(pack);
        this._ResetCDROM();
      }
    } else if (
      this._disconnectSet & this.FLOPPY_IMAGE_LINK &&
      this._establishedSet & this.FLOPPY_IMAGE_LINK
    ) {
      this._disconnectSet = this._disconnectSet & 0xfb;
      this._establishedSet = this._establishedSet & 0xfb;
      this._ufiProcessor = null;
      if (this._establishedSet === 0) {
        this._Reset();
      } else {
        const pack5 = new Uint8Array(12);
        pack5[0] = this.CLOSE_VM;
        pack5[1] = 1;
        pack5[2] = 0;
        this._ResetFloppy();
      }
    }
  }

  _ResetCDROM() {
    this._client.scope.cdDvd[0].disable = false;
    this._client.scope.cdDvd[1].disable = false;
    this._client.scope.cdDvd[2].disable = false;
    this._cdromConnect.disable = false;
    this._cdromInsert.disable = true;
    this._cdromConnect.text = 'HOME_CONNECT';
    this._cdromInsert.text = 'REMOTE_INSERT';
    if (
      (typeof this._cdromImageFile === 'undefined' || this._cdromImageFile == null) &&
      (typeof this._cdromDirectoryFile === 'undefined' || this._cdromDirectoryFile == null) &&
      this._cdromDirectoryFolders.length === 0
    ) {
      this._cdromConnect.disable = true;
    }
    if (this._client.scope.cdDvdSelected.value === 'iso') {
      this._cdromImage.uploaderConfig.disabled = false;
      this._cdromDirectory.uploaderConfig.disabled = true;
    } else {
      this._cdromImage.uploaderConfig.disabled = true;
      this._cdromDirectory.uploaderConfig.disabled = false;
      this._cdromFolders.uploaderConfig.disabled = false;
    }
  }

  _ResetFloppy() {
    this._floppyImage.uploaderConfig.disabled = false;
    this._floppyConnect.disable = false;
    this._floppyInsert.disable = true;
    this._floppyConnect.text = 'HOME_CONNECT';
    this._floppyInsert.text = 'REMOTE_INSERT';
    if (typeof this._floppyImageFile === 'undefined' || this._floppyImageFile == null) {
      this._floppyConnect.disable = true;
    }
  }

  _Reset() {
    clearInterval(this._monitorTimer);
    this._monitorTimer = null;
    this._state = this.STATE_INIT;
    if (this._sock !== null) {
      this._sock.close();
      this._sock.onopen = null;
      this._sock.onclose = null;
      this._sock.onerror = null;
      this._sock.onmessage = null;
      this._sock = null;
    }

    this._timeout = 0;
    this._disconnectSet = 0;
    this._connectingSet = 0;
    this._establishedSet = 0;
    this._ufiProcessor = null;
    this._sffProcessor = null;

    this._ResetCDROM();
    this._ResetFloppy();
  }

  _VMMLinkMonitor() {
    if (this._timeout++ > 20) {
      this._Reset();
    }
    switch (this._state) {
      case this.STATE_INIT:
        this._SendStateRequest();
        break;
      case this.STATE_ESTABLISHED:
        this._OpenDevice();
        this._CloseDevice();
        break;
      case this.STATE_ERROR:
        break;
      default:
    }
  }

  parserVmmState(data: number) {
    const vmmState = data;
    if (vmmState === 0) {
      this._client.showMessage(
        'SOCKET_CANNOT_CONNECT',
        'connectFailedDialog',
        'HOME_PERFWARNING',
        'warning'
      );
      this._Reset();
    }
    if (vmmState === 1 && this._state === this.STATE_STATE_REQUEST) {
      this._state++;
      this._timeout = 0;
      this._SendPortRequest();
    }
  }

  parserVmmPort(data: number) {
    this._port = data;
    if (this._state === this.STATE_PORT_REQUEST) {
      this._state++;
      this._timeout = 0;
      this._CreateConnection();
    }
  }

  _ResolveSecurityWarning() {
    const self = this;
    let interval = null as any;
    let times = 0;

    function receiver(event: any) {
      if (event.data === 'Certificate OK.') {
        clearInterval(interval);
        window.removeEventListener('message', receiver);
        self._CreateConnection();
      }
    }
    const targetOrigin = `https://${this._ip}:${this._port}`;
    const popupWin = window.open(targetOrigin, '_blank');
    if (popupWin) {
      popupWin.opener = null;
    }
    window.addEventListener('message', receiver);

    interval = setInterval(() => {
      popupWin?.postMessage('hello', targetOrigin);
      if (times++ > 150) {
        clearInterval(interval);
        window.removeEventListener('message', receiver);
        self._Reset();
      }
    }, 200);
  }

  _WSOpen(event: any) {
    this._securityWarning = 0;
    if (this._state === this.STATE_CONNECTING) {
      this._state++;
      this._timeout = 0;
      this._AuthConnection();
    }
  }

  _WSClose(event: any) {
    if (event?.code === 1015) {
      // 握手失败不需要重置
      return;
    }
    clearInterval(this._monitorTimer);
    // code值1008表示VMM会话超时
    if (event?.code === 1008) {
      this._client.showMessage('REMOTE_ERR_TIMEOUT', 'disconnectDialog', 'HOME_PERFWARNING', 'warning', true);
    // code值4001表示vmm会话被踢出
    }
    if (event?.code === 4001) {
      this._client.showMessage(
        'REMOTE_FORCED_LOGOUT_VMM',
        'errorVMDialog',
        'COMMON_ERROR',
        'error'
      );
    }
    this._Reset();
  }

  _WSError(event: any) {
    if (this._securityWarning === 1 && this._state === this.STATE_CONNECTING) {
      this._securityWarning = 0;
      this._ResolveSecurityWarning();
      return;
    } else {
      this._Reset();
    }
  }

  _WSMessage(event: any) {
    const data = new Uint8Array(event?.data);
    const { opcode, status, seq, bodyData } = packVmm.parseRspData(data);
    switch (opcode & 0xff) {
      case VmmCmdType.ACK:
        this._ACKProcess(data);
        if (this._isSffInit) {
          this._sffProcessor.process(this._sffData.seq, this._sffData.bodyData);
          this._isSffInit = false;
        }
        break;
      case VmmCmdType.HEARTBEAT: {
        const heartData = packVmm.packHeartBeat();
        this._Send(heartData);
        this._timeout = 0;
        break;
      }
      case VmmCmdType.DISCONNECT:
        this._CloseVM((status >> 4) & 0xf);
        break;
      case VmmCmdType.CLOSE_DEV:
        this._CloseVM(0);
        break;
      case VmmCmdType.TRAN_UFI:
        if (this._ufiProcessor != null) {
          this._ufiProcessor.process(seq, bodyData);
        }
        break;
      case VmmCmdType.TRAN_SFF:
        if (this._sffProcessor != null) {
          this._sffProcessor.process(seq, bodyData);
        } else {
          this._isSffInit = true;
          this._sffData = { seq, bodyData };
        }
        break;
      default:
        break;
    }
  }

  _Send(data: any) {
    if (this._sock != null && this._sock.readyState === 1) {
      this._sock.send(data.buffer);
    }
  }

  _ACKProcess(response: Uint8Array) {
    const sack = response[2];
    if (this._state === this.STATE_AUTHORING) {
      switch (sack) {
        case this.ACK_AUTH_OK:
          this._timeout = 0;
          this._state++;
          break;
        case this.ACK_INTERNAL_ERROR:
          this._Reset();
          this._client.showMessage('COMMON_FAILED', 'errorVMDialog', 'COMMON_ERROR', 'error');
          break;
        case this.ACK_VM_BUSY:
          this._Reset();
          this._client.showMessage(
            'REMOTE_ERR_BUSY_VM',
            'busyVMDialog',
            'HOME_PERFWARNING',
            'warning'
          );
          break;
        case this.ACK_AUTH_FAIL:
          this._Reset();
          this._client.showMessage(
            'COMMON_AUTH_FAIL',
            'authFailVMDialog',
            'HOME_PERFWARNING',
            'warning'
          );
          break;

        default:
          break;
      }
    } else if (this._state === this.STATE_ESTABLISHED) {
      if (sack === 0) {
        this._timeout = 0;
      } else if (sack === this.ACK_DEVICE_CREATED) {
        this._timeout = 0;
        if ((this._openDeviceSet & this.CDROM_IMAGE_LINK) === this.CDROM_IMAGE_LINK) {
          this._needReconnectCdrom = true;
          this._openDeviceSet = this._openDeviceSet & 0xfe;
          this._establishedSet = this._establishedSet | this.CDROM_IMAGE_LINK;
          this._sffProcessor = new SCSIProcessor(this, this._cdromImageFile, this.PROTOCOL_SFF);
          this._cdromConnect.disable = false;
          this._cdromConnect.text = 'HOME_DISCONNECT';
          this._cdromInsert.disable = false;
          this._cdromInsert.text = 'REMOTE_EJECT';
        } else if (
          (this._openDeviceSet & this.CDROM_DIRECTORY_LINK) ===
          this.CDROM_DIRECTORY_LINK
        ) {
          this._needReconnectCdrom = true;
          this._openDeviceSet = this._openDeviceSet & 0xfd;
          this._establishedSet = this._establishedSet | this.CDROM_DIRECTORY_LINK;
          this._sffProcessor = new SCSIProcessor(
            this,
            this._udfBuilder.fileBlob,
            this.PROTOCOL_SFF
          );
          this._cdromConnect.disable = false;
          this._cdromConnect.text = 'HOME_DISCONNECT';
          this._cdromInsert.disable = false;
          this._cdromInsert.text = 'REMOTE_EJECT';
        } else if ((this._openDeviceSet & this.FLOPPY_IMAGE_LINK) === this.FLOPPY_IMAGE_LINK) {
          this._needReconnectFloppy = true;
          this._openDeviceSet = this._openDeviceSet & 0xfb;
          this._establishedSet = this._establishedSet | this.FLOPPY_IMAGE_LINK;
          this._ufiProcessor = new SCSIProcessor(this, this._floppyImageFile, this.PROTOCOL_UFI);
          this._floppyConnect.disable = false;
          this._floppyInsert.disable = false;
          this._floppyConnect.text = 'HOME_DISCONNECT';
          this._floppyInsert.text = 'REMOTE_EJECT';
        }
      } else if (sack === this.ACK_DEVICE_FAIL) {
        this._timeout = 0;
        if ((this._openDeviceSet & this.CDROM_IMAGE_LINK) === this.CDROM_IMAGE_LINK) {
          this._openDeviceSet = this._openDeviceSet & 0xfe;
          if (this._establishedSet === 0) {
            this._Reset();
          } else {
            this._ResetCDROM();
          }
        } else if (
          (this._openDeviceSet & this.CDROM_DIRECTORY_LINK) ===
          this.CDROM_DIRECTORY_LINK
        ) {
          this._openDeviceSet = this._openDeviceSet & 0xfd;
          if (this._establishedSet === 0) {
            this._Reset();
          } else {
            this._ResetCDROM();
          }
        } else if ((this._openDeviceSet & this.FLOPPY_IMAGE_LINK) === this.FLOPPY_IMAGE_LINK) {
          this._openDeviceSet = this._openDeviceSet & 0xfb;
          if (this._establishedSet === 0) {
            this._Reset();
          } else {
            this._ResetFloppy();
          }
        }
      } else {
        return;
      }
    }
  }

  _CloseVM(type: number) {
    switch (type) {
      case 0:
      case 1:
      case 2:
        break;
      default:
    }
  }
}
