function hex(buffer) {
  const hexCodes = [];
  const view = new DataView(buffer);
  for (let i = 0; i < view.byteLength; i += 4) {
    const value = view.getUint32(i);
    const stringValue = value.toString(16);
    const padding = '00000000';
    const paddedValue = (padding + stringValue).slice(-padding.length);
    hexCodes.push(paddedValue);
  }
  return hexCodes.join('');
}
async function generateToken(appId, appKey, channelId, userId, timestamp) {
  const encoder = new TextEncoder();
  const data = encoder.encode(`${appId}${appKey}${channelId}${userId}${timestamp}`);
  const hash = await crypto.subtle.digest('SHA-256', data);
  return hex(hash);
}
function showToast(baseId, message) {
  $(`#${baseId}Body`).text(message);
  const toast = new bootstrap.Toast($(`#${baseId}`));
  toast.show();
}
// 填入您的应用ID 和 AppKey
const appId = '';
const appKey = '';
AliRtcEngine.setLogLevel(0);
let aliRtcEngine;
const remoteVideoElMap = {};
const remoteVideoContainer = document.querySelector('#remoteVideoContainer');
function removeRemoteVideo(userId, type = 'camera') {
  const vid = `${type}_${userId}`;
  const el = remoteVideoElMap[vid];
  if (el) {
    aliRtcEngine.setRemoteViewConfig(null, userId, type === 'camera' ? 1: 2);
    el.pause();
    remoteVideoContainer.removeChild(el);
    delete remoteVideoElMap[vid];
  }
}
function listenEvents() {
  if (!aliRtcEngine) {
    return;
  }
  // 监听远端用户上线
  aliRtcEngine.on('remoteUserOnLineNotify', (userId, elapsed) => {
    console.log(`用户 ${userId} 加入频道,耗时 ${elapsed} 秒`);
    // 这里处理您的业务逻辑,如展示这个用户的模块
    showToast('onlineToast', `用户 ${userId} 上线`);
  });
  // 监听远端用户下线
  aliRtcEngine.on('remoteUserOffLineNotify', (userId, reason) => {
    // reason 为原因码,具体含义请查看 API 文档
    console.log(`用户 ${userId} 离开频道,原因码: ${reason}`);
    // 这里处理您的业务逻辑,如销毁这个用户的模块
    showToast('offlineToast', `用户 ${userId} 下线`);
    removeRemoteVideo(userId, 'camera');
    removeRemoteVideo(userId, 'screen');
  });
  aliRtcEngine.on('bye', code => {
    // code 为原因码,具体含义请查看 API 文档
    console.log(`bye, code=${code}`);
    // 这里做您的处理业务,如退出通话页面等
    showToast('loginToast', `您已离开频道,原因码: ${code}`);
  });
  aliRtcEngine.on('videoSubscribeStateChanged', (userId, oldState, newState, interval, channelId) => {
    // oldState、newState 类型均为AliRtcSubscribeState,值包含 0(初始化)、1(未订阅)、2(订阅中)、3(已订阅)
    // interval 为两个状态之间的变化时间间隔,单位毫秒
    console.log(`频道 ${channelId} 远端用户 ${userId} 订阅状态由 ${oldState} 变为 ${newState}`);
    const vid = `camera_${userId}`;
    // 处理示例
    if (newState === 3) {
      const video = document.createElement('video');
      video.autoplay = true;
      // video.setAttribute(
      //   'style',
      //   'display: inline-block;width: 320px;height: 180px;background-color: black;margin-right: 8px;margin-bottom: 8px;'
      // );
      video.className = 'video';
      remoteVideoElMap[vid] = video;
      remoteVideoContainer.appendChild(video);
      // 第一个参数传入 HTMLVideoElement
      // 第二个参数传入远端用户 ID
      // 第三个参数支持传入 1 (预览相机流)、2(预览屏幕共享流)
      aliRtcEngine.setRemoteViewConfig(video, userId, 1);
    } else if (newState === 1) {
      removeRemoteVideo(userId, 'camera');
    }
  });
  aliRtcEngine.on('screenShareSubscribeStateChanged', (userId, oldState, newState, interval, channelId) => {
    // oldState、newState 类型均为AliRtcSubscribeState,值包含 0(初始化)、1(未订阅)、2(订阅中)、3(已订阅)
    // interval 为两个状态之间的变化时间间隔,单位毫秒
    console.log(`频道 ${channelId} 远端用户 ${userId} 屏幕流的订阅状态由 ${oldState} 变为 ${newState}`);
    const vid = `screen_${userId}`;
    // 处理示例    
    if (newState === 3) {
      const video = document.createElement('video');
      video.autoplay = true;
      video.className = 'video';
      remoteVideoElMap[vid] = video;
      remoteVideoContainer.appendChild(video);
      // 第一个参数传入 HTMLVideoElement
      // 第二个参数传入远端用户 ID
      // 第三个参数支持传入 1 (预览相机流)、2(预览屏幕共享流)
      aliRtcEngine.setRemoteViewConfig(video, userId, 2);
    } else if (newState === 1) {
      removeRemoteVideo(userId, 'screen');
    }
  });
  
  // 推屏幕流状态变化
  aliRtcEngine.on('screenSharePublishStateChanged', (oldState, newState, interval, channelId) => {
    // oldState、newState 类型均为AliRtcSubscribeState,值包含 0(初始化)、1(未发布)、2(发布中)、3(已发布)
    // interval 为两个状态之间的变化时间间隔,单位毫秒
    console.log(`频道 ${channelId} 本地屏幕流的推流状态由 ${oldState} 变为 ${newState}`);
    if (oldState === 3 && newState === 1) {
      showToast('screenToast', '已停推屏幕流');
    }
  });
}
$('#loginForm').submit(async e => {
  // 防止表单默认提交动作
  e.preventDefault();
  const channelId = $('#channelId').val();
  const userId = $('#userId').val();
  const timestamp = Math.floor(Date.now() / 1000) + 3600 * 3;
  if (!channelId || !userId) {
    showToast('loginToast', '数据不完整');
    return;
  }
  aliRtcEngine = AliRtcEngine.getInstance();
  listenEvents();
  try {
    const token = await generateToken(appId, appKey, channelId, userId, timestamp);
    // 设置频道模式,支持传入字符串 communication(通话模式)、interactive_live(互动模式)
    aliRtcEngine.setChannelProfile('communication');
    // 设置角色,互动模式时调用才生效
    // 支持传入字符串 interactive(互动角色,允许推拉流)、live(观众角色,仅允许拉流)
    // aliRtcEngine.setClientRole('interactive');
    // 加入频道,参数 token、nonce 等一般有服务端返回
    await aliRtcEngine.joinChannel(
      {
        channelId,
        userId,
        appId,
        token,
        timestamp,
      },
      userId
    );
    showToast('loginToast', '加入频道成功');
    $('#joinBtn').prop('disabled', true);
    $('#leaveBtn').prop('disabled', false);
    $('#boardBtn').prop('disabled', false);
    $('#screenBtn').prop('disabled', false);
    // 预览
    aliRtcEngine.setLocalViewConfig('localPreviewer', 1);
  } catch (error) {
    console.log('加入频道失败', error);
    showToast('loginToast', '加入频道失败');
  }
});
$('#leaveBtn').click(async () => {
  Object.keys(remoteVideoElMap).forEach(vid => {
    const arr = vid.split('_');
    removeRemoteVideo(arr[1], arr[0]);
  });
  // 停止本地预览
  await aliRtcEngine.stopPreview();
  // 离开频道
  await aliRtcEngine.leaveChannel();
  // 销毁实例
  aliRtcEngine.destroy();
  aliRtcEngine = undefined;
  $('#joinBtn').prop('disabled', false);
  $('#leaveBtn').prop('disabled', true);
  $('#boardBtn').prop('disabled', true);
  $('#screenBtn').prop('disabled', true);
  showToast('loginToast', '已离开频道');
});
// 这里填入您的网易云信白板的 AppKey 和 AppSecret
// 仅限本地开发体验,线上环境请勿露出 AppSecret
const boradAppKey = '';
const boradAppSecret = '';
const boradUid = Date.now(); // 易云信白板要求是数字uid
const boradNickname = boradUid.toString();
const boradChannel = '821937123';
async function sha1(data) {
  // 将字符串转换为ArrayBuffer
  const buffer = new TextEncoder().encode(data);
  
  // 使用Crypto API计算哈希值
  const digest = await crypto.subtle.digest('SHA-1', buffer);
  
  // 将ArrayBuffer转换为十六进制字符串
  const hashArray = Array.from(new Uint8Array(digest));
  const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
  
  return hashHex;
}
async function getAuthInfo() {
  const Nonce = 'xxxx';   //任意长度小于128位的随机字符串
  const curTime = Math.round((Date.now() / 1000)); //当前UTC时间戳,从1970年1月1日0点0分0秒开始到现在的秒数
  const checksum = await sha1(boradAppSecret + Nonce + curTime);
  return {
    nonce: Nonce,
    checksum: checksum,
    curTime: curTime
  };
}
// 创建白板实例
const boardIns = WhiteBoardSDK.getInstance({
  appKey: boradAppKey,
  nickname: boradNickname,     //非必须
  uid: boradUid,
  container: document.getElementById('whiteboard'),
  platform: 'web',
  record: false,   //是否开启录制
  getAuthInfo: getAuthInfo
});
let drawPluginIns;
// 登录白板房间
boardIns.joinRoom({
  channel: boradChannel,
  createRoom: true
})
.then((drawPlugin) => {
  drawPluginIns = drawPlugin;
  // 允许编辑
  drawPlugin.enableDraw(true);
  // 设置画笔颜色
  drawPlugin.setColor('rgb(243,0,0)');
  // 初始化工具栏
  const toolCollection = ToolCollection.getInstance({
      container: document.getElementById('whiteboard'),
      handler: drawPlugin,
      options: {
          platform: 'web'
      }
  });
  toolCollection.addOrSetTool({
    position: 'left',
    insertAfterTool: 'pan',
    item: {
      tool: 'uploadCenter',
      hint: '上传文档',
      supportPptToH5: true,
      supportDocToPic: true,
      supportUploadMedia: false, // 关闭上传多媒体文件
      supportTransMedia: false, // 关闭转码多媒体文件
    },
  });
  toolCollection.removeTool({ name: 'image' });
  
  // 显示工具栏
  toolCollection.show();
  // 监听文档事件
  toolCollection.on('docAdd', (newDocs, allDocs) => {
    console.log('add allDocs->', newDocs, allDocs);
    // 您可以在 docAdd 事件回调中将文档数据上传至您的服务端
    // 建议:服务端通过白板 channel 维度去储存
  });
  toolCollection.on('docDelete', (newDocs, allDocs) => {
    console.log('delete allDocs->', newDocs, allDocs);
    // 您可以在 docDelete 事件回调中将文档数据上传至您的服务端
    // 建议:服务端通过白板 channel 维度去储存
  });
  // 初始化后从服务端中获取该 channel 的文件列表,并更新至白板SDK中
  // fetch('/docList', (list) => {
  //   toolCollection.setDefaultDocList(list);
  // });
});
$('#screenBtn').click(async() => {
  if (!aliRtcEngine) {
    showToast('screenToast', 'sdk 未准备好');
    return;
  }
  try {
    await aliRtcEngine.startScreenShare();
    showToast('screenToast', '推屏幕成功');
  } catch (error) {
    showToast('screenToast', '推屏幕失败');
  }
});
$('#boardBtn').click(async() => {
  if (!aliRtcEngine || !drawPluginIns) {
    showToast('screenToast', 'sdk 未准备好');
    return;
  }
  const mediaStream = drawPluginIns.getStream({
    width: 720,
    frameRate: 15,
  });
  const videoTrack = mediaStream.getVideoTracks()[0];
  if (videoTrack) {
    try {
      await aliRtcEngine.startScreenShare({
        videoTrack,
      });
      showToast('screenToast', '推白板成功');
    } catch (error) {
      showToast('screenToast', '推白板失败');
    }
  } else {
    showToast('screenToast', '无白板 videoTrack');
  }
});