import { useMemo } from 'react';
import { SHARE_ID } from '../utils/agora-rtc-client';
// import _ from 'lodash';
import { roomStore } from '../stores/room';
import { useRoomState } from '../containers/root-container';
// import {STAGE_NUM} from "../utils/consts";

type StreamValue ={
  teacher: any
  students: any[]
  sharedStream: any
  currentHost: any
  onPlayerClick: (type: string, streamID: number, uid: string) => Promise<any>
}


export default function useStream () {
  const roomState = useRoomState();
  const me = roomState.me;
  const course = roomState.course;

  const teacher = useMemo(() => {
    if (!course.teacherId || !me.uid) return;
    const teacherInfo = roomStore.state.users.get(''+course.teacherId);
    if (!teacherInfo) return;
    if (me.uid === course.teacherId) {
      return {
        ...roomState.rtc.localStream,
        account: teacherInfo.account,
        video: teacherInfo.video,
        audio: teacherInfo.audio,
        local: true,
      }
    } else {
      // when peer teacher is online
      const teacherUid = roomState.rtc.users.get(+course.teacherId);
      if(!teacherUid) return null;
      // when peer teacher stream is found
      const remoteTeacherStream = roomState.rtc.remoteStreams.get(teacherUid);
      if (remoteTeacherStream) {
        return {
          ...remoteTeacherStream,
          account: teacherInfo.account,
          video: teacherInfo.video,
          audio: teacherInfo.audio,
        }
      }
      return {
        streamID: teacherUid,
        account: teacherInfo.account,
        video: teacherInfo.video,
        audio: teacherInfo.audio,
      }
    }
  }, [
    course,
    me.uid,
    roomState.rtc.users,
    roomState.rtc.remoteStreams,
    roomState.rtc.localStream
  ]);
  /*
  const students__ = useMemo(() => {
    const userAttrs = roomStore.state.users;
    if (!me.uid || userAttrs.count() === 0) return [];
    const teacherUid = course.teacherId;
    const peerUsers = roomState.rtc.users;
    // exclude teacher and me
    let studentIds = peerUsers.filter((it: number) => it !== +teacherUid && it !== +me.uid && it !== SHARE_ID);

    const studentStreams: any[] = [];
    const myAttr = userAttrs.get(me.uid);
    const ss = [];
    // when i m student
    if (me.role === 'student') {
      if (myAttr && roomState.rtc.localStream) {
        const _tmpStream = {
          ...roomState.rtc.localStream,
          account: myAttr.account,
          video: myAttr.video,
          audio: myAttr.audio,
          local: true,
        }
        studentStreams.push(_tmpStream);
        ss.push(me.uid)
      }
    }

    for (let studentId of studentIds) {
      ss.push(studentId)
    }
    console.log('studentIds', ss.join(', '))

    // capture all remote streams
    for (let studentId of studentIds) {
      const studentAttr = userAttrs.get(''+studentId);
      const stream = roomState.rtc.remoteStreams.get(+studentId);
      if (studentAttr) {
        let _tmpStream = {
          streamID: studentId,
          account: studentAttr.account,
          video: studentAttr.video,
          audio: studentAttr.audio,
        }
        if (stream) {
          _tmpStream = {
            ...stream,
            streamID: studentId,
            account: studentAttr.account,
            video: studentAttr.video,
            audio: studentAttr.audio,
          }
        }
        studentStreams.push(_tmpStream);
      }
    }
    console.log('studentStreams', studentStreams)
    return studentStreams;
  }, [
    course,
    me.uid,
    roomState.rtc.users,
    roomState.rtc.remoteStreams,
    roomState.rtc.localStream
  ]);
  */
  const students = useMemo(() => {
    const userAttrs = roomStore.state.users;
    if (!me.uid || userAttrs.count() === 0) return [];
    const teacherUid = course.teacherId;
    const peerUsers = roomState.rtc.users;
    const studentsOrder = [...roomStore.state.studentsOrder] || [];
    // exclude teacher and me
    let studentIds = peerUsers.filter((it: number) => studentsOrder.includes(it) && `${it}` !== `${teacherUid}` && `${it}` !== `${me.uid}` && `${it}` !== `${SHARE_ID}`);
    if (me.role !== 'teacher') {
      studentIds = studentIds.add(+me.uid);
    }

    const studentStreams: any[] = [];
    const myAttr = userAttrs.get(me.uid);


    // console.log(100000, studentsOrder);
    // console.log(11111111, studentIds.toArray());
    // studentIds = studentIds.sort(function(a, b){
    //   if (studentsOrder.indexOf(+a) < 0) {return 0}
    //   if (studentsOrder.indexOf(+b) < 0) {return 0}
    //   return studentsOrder.indexOf(+a) - studentsOrder.indexOf(+b);
    // });
    const sids: any = [];
    let orderIdx = 0;
    for (const ouid of studentsOrder) {
      if (ouid === 0) {
        sids.push(0)
      } else {
        // find in peer
        const uid = studentIds.find((it: number) => `${ouid}` === `${it}`);
        if (uid) {
          sids.push(uid);
          roomStore.releaseWaitStreamHandle(+uid);
        } else {
          // find in channel
          const usr = userAttrs.get(`${ouid}`)
          console.log('channel has ', ouid, usr)
          if (usr) {
            sids.push(-usr.uid);
            console.log('add waiting handle', usr.uid)
            roomStore.lockWaitStreamHandle(+usr.uid);
          } else {
            // sids.push(-1);
            sids[orderIdx] = 0;
            studentsOrder[orderIdx] = 0;
            /*
            const _tmpStream = {
              account: '空闲',
              streamID: 0,
              video: 0,
              audio: 0,
              local: false,
            }
            studentStreams.push(_tmpStream);
            */
          }
        }
      }
      orderIdx++
    }
    // console.log(222222, userAttrs.toArray());
    // console.log(333333, sids);



    // capture all remote streams
    for (let studentId of /*studentIds*/sids) {
      // console.log('*****************', studentId)
      if (studentId === undefined) {

        continue
      }
      if (studentId === 0) {
        const _tmpStream = {
          account: '空闲',
          streamID: studentId,
          video: 0,
          audio: 0,
          local: false,
        }
        studentStreams.push(_tmpStream);
        continue
      }
      if (studentId < 0 ) {
        const _tmpStream = {
          account: '等待中...',
          streamID: studentId,
          video: 0,
          audio: 0,
          local: false,
        }
        studentStreams.push(_tmpStream);
        continue
      }

      if (me.role === 'student' && +me.uid === studentId) {
        if (myAttr && roomState.rtc.localStream) {
          // console.log('use local stream')
          const _tmpStream = {
            ...roomState.rtc.localStream,
            account: myAttr.account,
            video: myAttr.video,
            audio: myAttr.audio, // roomState.course.muteAudio ? 0 : myAttr.audio,
            local: true,
          }
          studentStreams.push(_tmpStream);
          continue
        }
      }

      const studentAttr = userAttrs.get(''+studentId);
      const stream = roomState.rtc.remoteStreams.get(+studentId);
      if (studentAttr) {
        let _tmpStream = {
          streamID: studentId,
          account: studentAttr.account,
          video: studentAttr.video,
          audio: studentAttr.audio, // roomState.course.muteAudio ? 0 : studentAttr.audio,
        }
        if (stream) {
          _tmpStream = {
            ...stream,
            streamID: studentId,
            account: studentAttr.account,
            video: studentAttr.video,
            audio: studentAttr.audio , // roomState.course.muteAudio ? 0 : studentAttr.audio,
          }
        }
        studentStreams.push(_tmpStream);
      } else {
        const _tmpStream = {
          account: '空闲',
          streamID: 0,
          video: 0,
          audio: 0,
          local: false,
        }
        studentStreams.push(_tmpStream);
      }
    }
    userAttrs.forEach((v, k) => {
      if (!sids.includes(+v.uid)) {
        if (`${v.uid}` !== `${teacherUid}`) {
          const s: any = {
            streamID: +v.uid,
            account: v.account,
            video: v.video,
            audio: v.audio, // roomState.course.muteAudio ? 0 : v.audio,
          }
          if (`${me.uid}` === `${v.uid}`) {
            s.local = true;
          }
          studentStreams.push(s)
        }
      }
    })
    // console.log('studentStreams', studentStreams);
    return studentStreams;
    // eslint-disable-next-line
  }, [
    // course,
    me.uid,
    roomStore.state.studentsOrder,
    roomState.users,
    roomState.rtc.users,
    roomState.rtc.remoteStreams,
    roomState.rtc.localStream
  ]);

  /*
  const stageStudents:  { wait: any[]; stage: any[] } = useMemo(() => {
    const userAttrs = roomStore.state.users;
    if (!me.uid || userAttrs.count() === 0) return { wait: [], stage:[] };
    const teacherUid = course.teacherId;
    const peerUsers = roomState.rtc.users;
    // exclude teacher and me
    let studentIds = peerUsers.filter((it: number) => it !== +teacherUid && it !== +me.uid && it !== SHARE_ID);
    const studentStreams: any[] = [];
    userAttrs.forEach(u => {
      const uid = u.uid;
      if (me.role === 'student' && `${uid}` === `${me.uid}`) {
        if (roomState.rtc.localStream) {
          const _tmpStream = {
            ...roomState.rtc.localStream,
            account: u.account,
            video: u.video,
            audio: u.audio,
            local: true,
          }
          studentStreams.push(_tmpStream);
        }
      } else {
        const studentAttr = userAttrs.get(`${uid}`);
        const stream = roomState.rtc.remoteStreams.get(+uid);
        if (studentAttr) {
          let _tmpStream = {
            streamID: uid,
            account: studentAttr.account,
            video: studentAttr.video,
            audio: studentAttr.audio,
          }
          if (stream) {
            _tmpStream = {
              ...stream,
              streamID: uid,
              account: studentAttr.account,
              video: studentAttr.video,
              audio: studentAttr.audio,
            }
          }
          studentStreams.push(_tmpStream);
        }
      }
    })
    console.log('studentStreams', studentStreams)
    return {
      stage: [...studentStreams.slice(0,STAGE_NUM)],
      wait: [...studentStreams.slice(STAGE_NUM)]
    };
  }, [
    course,
    me.uid,
    roomState.rtc.users,
    roomState.rtc.remoteStreams,
    roomState.rtc.localStream
  ]);
  */


  const sharedStream = useMemo(() => {
    const sharedUid = SHARE_ID;
    if (roomState.rtc.localSharedStream) {
      const _tmpStream = {
        ...roomState.rtc.localSharedStream,
        video: 1,
        audio: 1,
      }
      return _tmpStream;
    }

    const remoteStream = roomState.rtc.remoteStreams.get(sharedUid);

    if (remoteStream) {
      const _tmpStream = {
        ...remoteStream,
        video: 1,
        audio: 1,
      }
      return _tmpStream;
    }

    return null;
  }, [roomState.rtc.remoteStreams, roomState.rtc.localSharedStream]);

  const currentHost = useMemo(() => {
    if (!course.linkId) return null;
    const linkId = ''+course.linkId;
    const userAttr = roomState.users.get(linkId);
    if (!userAttr) return null;
    // when i am current broadcaster
    if (me.uid === linkId) {
      if (roomState.rtc.localStream) {
        let _tmpStream = {
          ...roomState.rtc.localStream,
          account: userAttr.account,
          video: userAttr.video,
          audio: userAttr.audio,
          local: true,
          streamID: +me.uid,
        }
        return _tmpStream;
      }
    } else {
      // when remote user is broadcaster
      const peerUid = course.linkId;
      const peerUserAttr = roomState.users.get(''+peerUid);
      if (peerUid && peerUserAttr) {
        const remoteStream = roomState.rtc.remoteStreams.get(peerUid);
        if (remoteStream) {
          let _tmpStream = {
            ...remoteStream,
            account: peerUserAttr.account,
            video: peerUserAttr.video,
            audio: peerUserAttr.audio,
            streamID: +peerUid,
          }
          return _tmpStream;
        }
      }
    }
    return null;
    // eslint-disable-next-line
  }, [
    course,
    me.uid,
    roomState.rtc.remoteStreams,
    roomState.rtc.localStream,
  ]);

  const value: StreamValue = {
    teacher: teacher,
    students: students,
    // stageStudents,
    sharedStream: sharedStream,
    currentHost: currentHost,
    onPlayerClick: async (type: string, streamID: number, uid: string) => {

      console.log(" click player ", type, streamID, uid);
      const me = roomStore.state.me;
      if (!roomStore.state.rtm.joined || !me.uid) return console.warn("please confirm joined rtm");
      const targetUser = roomStore.state.users.get(uid);
      console.log("targetUser : ", targetUser);
      if (!targetUser) return;

      const targetUid = targetUser.uid;

      console.log(" click >>> targetUid: ", targetUid, " type: ", type, " streamID: ", streamID, " uid: ", uid);

      const video = Boolean(targetUser.video);
      const audio = Boolean(targetUser.audio);
      const chat = Boolean(targetUser.chat);

      if (type === 'video') {
        if (video) {
          await roomStore.mute(targetUid, 'video');
        } else {
          await roomStore.unmute(targetUid, 'video');
        }
        return;
      }

      if (type === 'audio') {
        if (audio) {
          await roomStore.mute(targetUid, 'audio');
        } else {
          if (me.role === 'student' && roomStore.state.course.muteAudio) {
            return
          }
          await roomStore.unmute(targetUid, 'audio');
        }
        return;
      }

      if (type === 'chat') {
        if (chat) {
          await roomStore.mute(targetUid, 'chat');
        } else {
          await roomStore.unmute(targetUid, 'chat');
        }
        return;
      }
      ///////////////////////////////////////////////////////
      // const stage = Boolean(targetUser.stage);
      if (type === 'stageUp') {
        // if (stage) {
        //
        // } else {
        //   await roomStore.stageUp(targetUid);
        // }
        await roomStore.stageUp(targetUid);
        return;
      }
      if (type === 'stageDown') {
        await roomStore.stageDown(targetUid);
        // if (stage) {
        //   await roomStore.stageDown(targetUid);
        // }
        return;
      }
      if (type === 'fixUserStream') {
        await roomStore.unPublishMeStream();
        await roomStore.publishMeStream();
      }

    }
  }
  return value;
}
