"use strict";

require("core-js/modules/web.dom-collections.iterator.js");

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;

var _socket = _interopRequireDefault(require("socket.io-client"));

var THREE = _interopRequireWildcard(require("three"));

var _config = _interopRequireDefault(require("next/config"));

function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }

function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

const {
  publicRuntimeConfig
} = (0, _config.default)(); // import AgoraRTC from "agora-rtc-sdk-ng"

const socketEndpoint = publicRuntimeConfig.CONFIG.channelEndpoint;
const tmpOffset1 = new THREE.Vector3();
const tmpOffset2 = new THREE.Vector3();

class SocketController {
  constructor() {
    this.verseZone = '7VerseMallB';
    this.channelId = 99;
    this.rtc = {
      // For the local client.
      client: null,
      // For the local audio track.
      localAudioTrack: null
    };
    this.playerId = -1;
    this.playerName = null;
    this.verseRoomId = null;
    this.isSendingVoice = false;
    this.savedUpdatedData = null;
    this.didLogInSuccess = false;
    this.didTryToLogin = false;
    this.didTryToEnterChannel = false;
    this.cachedPlayerDatas = {};
    this.audioPublishers = {};
    this.cachedSelfData = null;
    this.socket = (0, _socket.default)(socketEndpoint, {
      reconnection: true,
      transports: ['websocket'],
      timeout: 10000
    });
    console.log('created socket');
    this.socket.on("connect", () => {
      console.log('connected!');

      if (this.playerId === -1) {
        // not ready to login
        return;
      }

      console.log('loggin in');
      this.doLoginSocket();
    });
    this.socket.on('login.success', () => {
      this.handleLoginSuccess();
    });
    this.socket.on('enter.verse.channel.success', (joinedVerseZone, joinedChannelId) => {
      if (this.verseRoomId !== null) {
        // already entered
        return;
      }

      console.log('enter.verse.channel.success: ' + joinedVerseZone + joinedChannelId);
      this.verseRoomId = joinedVerseZone + joinedChannelId;
      this.startSendingPing();
    });
    this.socket.on('verse.channel.update.all', (updatedDatas, nodeId) => {
      // update all transforms every 15 seconds
      // updatedData = [playerId, state, position, quaternion]
      // updatedData = [playerId, state, [x,y,z], [x,y,z,w]]
      // console.log('verse.channel.update.all')
      // update previous frame
      // if(this.savedUpdatedData !== null) {
      //   this.onVerseRoomUpdateCallback && this.onVerseRoomUpdateCallback(this.savedUpdatedData.type,this.savedUpdatedData.updatedDatas)
      // }
      // this.savedUpdatedData = {
      //   type:'all',
      //   updatedDatas: updatedDatas.filter((updatedData) => updatedData[0]!==this.playerId)
      // }
      this.updateChannelDatas(updatedDatas);
    });
    this.socket.on('verse.channel.update', (updatedDatas, nodeId) => {
      // update updated datas
      // updatedData = [playerId, state, position, quaternion]
      // updatedData = [playerId, state, [x,y,z], [x,y,z,w]]
      // console.log('verse.channel.update')
      // update previous frame
      // if(this.savedUpdatedData !== null) {
      //   this.onVerseRoomUpdateCallback && this.onVerseRoomUpdateCallback(this.savedUpdatedData.type,this.savedUpdatedData.updatedDatas)
      // }
      // // do not update self
      // this.savedUpdatedData = {
      //   type:'updated',
      //   updatedDatas: updatedDatas.filter((updatedData) => updatedData[0]!==this.playerId)
      // }
      this.updateChannelDatas(updatedDatas);
    }); // this.socket.on("audio.join.success", (data) => {
    //   const rtmToken = data[0];
    //   this.rtc.client = AgoraRTC.createClient({ mode: "rtc", codec: "vp8" });
    //   this.rtc.client.join('2ad99ad94e94419e89b2651eab7b44e3', this.verseRoomId, rtmToken, ''+this.playerId).then(() => {
    //     this.sendChatMsg('room','joined Voice Chat',null)
    //     this.rtc.client.on("user-published", async (user, mediaType) => {
    //       await this.rtc.client.subscribe(user, mediaType);
    //       console.log("subscribe success");
    //       // If the remote user publishes an audio track.
    //       if (mediaType === "audio") {
    //         // Get the RemoteAudioTrack object in the AgoraRTCRemoteUser object.
    //         const remoteAudioTrack = user.audioTrack;
    //         this.audioPublishers[user.uid] = remoteAudioTrack;
    //         const cachedPublisherData = this.cachedPlayerDatas[user.uid];
    //         if(cachedPublisherData && this.cachedSelfData) {
    //           this.adjustAudioVolume(cachedPublisherData, remoteAudioTrack);
    //         }
    //         // Play the remote audio track. No need to pass any DOM element.
    //         remoteAudioTrack.play();
    //       }
    //     });
    //     // Listen for the "user-unpublished" event
    //     this.rtc.client.on("user-unpublished", user => {
    //         // Get the dynamically created DIV container.
    //         // const remotePlayerContainer = document.getElementById(user.uid);
    //         // // Destroy the container.
    //         // remotePlayerContainer.remove();
    //         console.log('user-unpublished: '+user.uid);
    //         this.audioPublishers[user.uid] = null;
    //     });
    //     AgoraRTC.createMicrophoneAudioTrack().then((localAudioTrack) => {
    //       this.rtc.localAudioTrack = localAudioTrack;
    //       this.rtc.client.publish([this.rtc.localAudioTrack]);
    //     });
    //   });
    // });
    // this.socket.on("chat.msg.receive", (data) => {
    //   const mode = data[0]
    //   const msg = data[1]
    //   const senderId = data[2]
    //   const senderDisplayName = data[3]
    //   console.log('mode:'+mode)
    //   console.log('msg:'+msg)
    //   console.log('sender:'+senderId)
    //   console.log('sender:'+senderDisplayName)
    // })

    this.socket.on("disconnect", () => {
      console.log('disconnected!');
      this.didTryToLogin = false;
    });
  }

  adjustAudioVolume(cachedPublisherData, remoteAudioTrack) {
    tmpOffset1.set(cachedPublisherData[2][0], cachedPublisherData[2][1], cachedPublisherData[2][2]);
    tmpOffset2.set(this.cachedSelfData[2][0], this.cachedSelfData[2][1], this.cachedSelfData[2][2]);
    const soundDistance = tmpOffset1.distanceTo(tmpOffset2);
    const newVolume = Math.max(30 - soundDistance, 0) / 30.0 * 100.0;
    remoteAudioTrack.setVolume(newVolume);
  }

  updateChannelDatas(updatedDatas) {
    const cachedSelfData = updatedDatas.find(a => a[0] === this.playerId);

    if (cachedSelfData) {
      this.cachedSelfData = cachedSelfData;
    }

    updatedDatas.forEach(updatedData => {
      const theUserId = updatedData[0];
      this.cachedPlayerDatas[theUserId] = updatedData;
      const remoteAudioTrack = this.audioPublishers[theUserId];

      if (remoteAudioTrack && this.cachedSelfData) {
        this.adjustAudioVolume(updatedData, remoteAudioTrack);
      }
    });
  }

  tryToEnterChannel() {
    if (this.didTryToEnterChannel) {
      return;
    }

    if (this.verseZone && this.channelId) {
      this.didTryToEnterChannel = true;
      this.socket.emit('enter.verse.channel', this.verseZone, this.channelId);
    }
  }

  handleLoginSuccess() {
    this.didLogInSuccess = true;
    this.tryToEnterChannel();
  }

  setVerseZoneAndChannelId(inverseZone, inchannelId) {
    if (this.verseZone !== inverseZone || this.channelId !== inchannelId) {
      // if already config
      // TO DO handle leave channel
      console.log('enter.verse.channel', inverseZone, inchannelId);
      this.socket.emit('leave.verse.channel', this.verseZone, this.channelId);
      this.socket.emit('enter.verse.channel', inverseZone, inchannelId);
      this.verseRoomId = inverseZone + inchannelId;
    }

    this.verseZone = inverseZone;
    this.channelId = inchannelId;
    this.tryToEnterChannel();
  }

  sendChatMsg(mode, msg, receiver) {
    this.socket.emit('chat.msg.send', [mode, msg, receiver]);
  }

  setPlayer(fid, name) {
    console.log('setPlayer: ' + fid);
    this.playerId = fid;
    this.playerName = name;
    this.doLoginSocket();
  }

  startSendingVoice() {
    if (this.isSendingVoice) {
      return;
    }

    this.socket.emit('audio.join');
    this.isSendingVoice = true;
  }

  doLoginSocket() {
    if (!this.didTryToLogin) {
      this.didTryToLogin = true;
      console.log('really emit login');
      this.socket.emit('login', [this.playerId, this.playerName]);
    }
  }

  stopSendingVoice() {
    if (!this.isSendingVoice) {
      return;
    }

    this.isSendingVoice = false;
    this.sendChatMsg('room', 'left Voice Chat', null);
    this.rtc.client.leave();
  }

  startSendingPing() {
    this.sendPing();
  }

  sendPing() {
    if (this.socket.connected) {
      this.socket.emit('ping');
      setTimeout(() => {
        this.startSendingPing();
      }, 1000);
    }
  }

  onVerseRoomUpdate(cb) {
    this.onVerseRoomUpdateCallback = cb;
  }

  SendUpdatedTransform(updatedState, updatedPosition, updatedQuaternion, emoji) {
    if (this.verseRoomId === null) {
      return;
    }

    this.socket.emit('update.transform', [updatedState, [updatedPosition.x, updatedPosition.y, updatedPosition.z], [updatedQuaternion.x, updatedQuaternion.y, updatedQuaternion.z, updatedQuaternion.w], emoji]);
  }

}

var _default = SocketController;
exports.default = _default;