import { Injectable, OnModuleInit } from '@nestjs/common';
import { ClientGrpc, Client } from '@nestjs/microservices';
import { grpcClientOptions } from './grpc-scene.options';
import { Logger } from '@nestjs/common';
import { DataChannel } from 'node-datachannel';
import * as path from 'path';
import { statSync, createReadStream } from 'fs';
import multistream from 'multistream';
import { Readable } from 'stream';

@Injectable()
export class SceneService implements OnModuleInit {
  // constructor(private redisService: RedisService) {}
  @Client(grpcClientOptions) private readonly client: ClientGrpc;
  private sceneGrpcService: SceneGrpcService;

  private logger: Logger = new Logger('SceneService');
  private frameCnt = -1;
  private frameCntInterval = 1000;
  public _frameInteval: NodeJS.Timeout;
  private channel: DataChannel;
  private onSteaming = false;

  onModuleInit() {
    this.sceneGrpcService =
      this.client.getService<SceneGrpcService>('SceneGrpcService');
    this.logger.log('init SceneGrpcService');
  }

  getRoute(request: RouteRequest) {
    return this.sceneGrpcService.getRoute(request);
  }
  getBreakPoint(request: GetBreakPointRequest) {
    return this.sceneGrpcService.getBreakPoint(request);
  }

  init(request: string) {
    try {
      console.log('request', this.sceneGrpcService);
      const params = JSON.parse(request);
      // const requestData: InitRequest = {
      //   appId: params.appId
      // }
      const demo_test: InitRequest = {
        user_id: '92dd7e2f-cca9-495d-8f16-458e628ea827',
        nick_name: 'Hello',
        skin_id: 'ce098a8f-a7fc-4721-9c37-31bdbc580c59',
        avatar_id: 'c961561e-78e5-4478-b158-944e3b9c9287',
        room_id: 'c38187b6-d4af-44bb-8028-7ad1e5461cd8',
        app_id: '2282e1b5-6129-4e0d-a30b-2339a1c761cd',
        player: {
          position: {
            x: '0.0',
            y: '0.0',
            z: '0.0',
          },
          angle: {
            pitch: 10,
            yaw: 10,
            roll: 10,
          },
        },
      };
      const name = {
        name: 'Hello',
      };
      const initReply = this.sceneGrpcService.test(name);
      // initReply.subscribe((val) => {
      //   console.log('val', val);
      // });
    } catch (error) {
      console.log('error', error);
    }
  }

  move(request: MoveRequest) {
    return this.sceneGrpcService.move(request);
  }

  rotate(request: RotateRequest) {
    return this.sceneGrpcService.rotate(request);
  }

  joystick(request: JoystickRequest) {
    return this.sceneGrpcService.joystick(request);
  }

  handleDataChanelOpen(channel: DataChannel): void {
    this.channel = channel;
    this.handleStartCountingFrame();
  }

  handleDataChanelClose(): void {
    this.stopCountingFrame();
  }

  handleMessage(event: string | Buffer) {
    console.log('get rtc message', event);
  }
  handleStartCountingFrame() {
    this._frameInteval = setInterval(async () => {
      this.frameCnt += 1;
      try {
        // console.log()
        // const data = this.redisService.get('test');
        if (this.frameCnt === 1) {
          this.pushTheFirstFrame();
        }

        // console.log('11', await this.redisService.get('test'));
        // console.log('data', data);
        if (this.frameCnt > 1) {
          let demo = `{ "traceIds": [],"vehicle": null, "newUserStates": [{ "userId": "a2aaaed1fffe6", "playerState": { "roomTypeId": "", "person": 0, "avatarId": "", "skinId": "", "roomId": "", "isHost": false, "isFollowHost": false, "skinDataVersion": "", "avatarComponents": "", "nickName": "", "movingMode": 0, "attitude": "", "areaName": "", "pathName": "", "pathId": "", "avatarSize": 1, "extra": "", "prioritySync": false, "player": { "position": { "x": -755, "y": -1450, "z": -34 }, "angle": { "pitch": 0, "yaw": 0, "roll": 0 } }, "camera": { "position": { "x": -1075, "y": -1450, "z": 86 }, "angle": { "pitch": 0, "yaw": 0, "roll": 0 } }, "cameraCenter": { "x": -755, "y": -1450, "z": -34 } }, "renderInfo": { "renderType": 0, "videoFrame": null, "cameraStateType": 0, "isMoving": 0, "needIfr": 0, "isVideo": 0, "stillFrame": 0, "isRotating": 0, "isFollowing": 0, "clientPanoTitlesBitmap": [], "clientPanoTreceId": "", "prefetchVideoId": "", "noMedia": false }, "event": null, "relation": 1 }], "actionResponses": [], "getStateType": 0, "code": 0, "msg": "OK" }`;
          demo = demo.replace(/\s/g, '');
          const buff = Buffer.from(demo, 'utf-8');

          const block = 36;
          const blockBuff = Buffer.alloc(block);
          // const packArrayBuffer = new ArrayBuffer(buff.byteLength + block);
          const packBuffer = Buffer.concat([blockBuff, buff]);

          const statusPack = new DataView(
            packBuffer.buffer.slice(
              packBuffer.byteOffset,
              packBuffer.byteOffset + packBuffer.byteLength,
            ),
          );

          statusPack.setUint32(0, 1437227610);
          // 16 bit slot
          statusPack.setUint16(6, block);
          statusPack.setUint16(8, this.frameCnt);
          statusPack.setUint16(10, 1);
          statusPack.setUint16(24, 0);
          statusPack.setUint16(26, 0);

          // 32 bit slot
          statusPack.setUint32(12, buff.byteLength);
          statusPack.setUint32(16, 0);
          // statusPack.setUint32(20, 0);
          statusPack.setUint32(24, 0);
          statusPack.setUint32(28, 0);
          statusPack.setUint32(32, 0);

          if (this.channel.isOpen()) {
            this.channel.sendMessageBinary(Buffer.from(statusPack.buffer));
          }
        }
      } catch (error) {
        console.log('error', error);
      }
    }, this.frameCntInterval);
  }

  stopCountingFrame(): void {
    clearInterval(this._frameInteval);
    this.frameCnt = -1;
  }
  // 首屏渲染
  pushTheFirstFrame() {
    const chunk_size = 16000;
    const block = 36;
    console.log('首屏--数据');
    const paths = path.join(__dirname, '../ws/video');
    const clipPath = paths + `/testframe.h264`;
    let metaData = ` {"traceIds":[],"vehicle":null,"newUserStates":[{"userId":"33df57eed8e42","playerState":{"roomTypeId":"","person":0,"avatarId":"KGe_Boy","skinId":"10089","roomId":"","isHost":false,"isFollowHost":false,"skinDataVersion":"1008900008","avatarComponents":"","nickName":"33df57eed8e42","movingMode":0,"attitude":"walk","areaName":"LQC","pathName":"thirdwalk","pathId":"thirdwalk","avatarSize":1,"extra":"{\"removeWhenDisconnected\":true}","prioritySync":false,"avatarURL":"","micStatus":0,"player":{"position":{"x":-755,"y":-1450,"z":-34},"angle":{"pitch":0,"yaw":0,"roll":0}},"camera":{"position":{"x":-1075,"y":-1450,"z":86},"angle":{"pitch":0,"yaw":0,"roll":0}},"cameraCenter":null},"renderInfo":{"renderType":0,"videoFrame":null,"cameraStateType":0,"isMoving":0,"needIfr":0,"isVideo":0,"stillFrame":0,"isRotating":0,"isFollowing":0,"clientPanoTitlesBitmap":[],"clientPanoTreceId":"","prefetchVideoId":"","noMedia":false},"event":{"id":"","type":0,"points":[],"rotateEvent":null,"removeVisitorEvent":null},"relation":1}],"actionResponses":[],"getStateType":0,"code":0,"msg":"OK"} `;
    metaData = metaData.replace(/\s/g, '');

    const coordBuff = Buffer.from(metaData, 'utf-8');

    console.warn('coordBuff', coordBuff.byteLength);

    const steamStat = statSync(clipPath);

    // const steamTotalSize = metaData.length + steamStat.size;


    const steam = createReadStream(clipPath, {
      highWaterMark: chunk_size - block,
    });

    // const mergeSteam = MergeSteam(coordBuff, steam);

    let steamByteLength = 0;

    steam.on('data', (data: Buffer) => {
      // console.log('data', data.byteLength);
      console.log('steamStat-size', steamStat.size);
      const blockBuffStart = Buffer.alloc(block);

      let packBuffer = Buffer.concat([blockBuffStart, data]);

      const isLastFrame = packBuffer.byteLength - chunk_size < 0;
      console.log('packBuffer', packBuffer.byteLength);
      if (isLastFrame) {
        // last frame
        packBuffer = Buffer.concat([packBuffer, coordBuff]);
        console.log('last frame', packBuffer.byteLength);
      }

      const framePack = new DataView(
        packBuffer.buffer.slice(
          packBuffer.byteOffset,
          packBuffer.byteOffset + packBuffer.byteLength,
        ),
      );

      // 16 bit slot
      // framePack.setUint32(4)
      framePack.setUint16(6, block);
      framePack.setUint16(8, 1); // first render cnt
      framePack.setUint16(10, 1); // isDIR
      framePack.setUint16(24, 0);
      framePack.setUint16(26, 0);

      // 32 bit slot
      // statusPack.setUint32(12, buff.byteLength);
      framePack.setUint32(0, 1437227610);
      framePack.setUint32(12, metaData.length); // metaLen
      framePack.setUint32(16, steamStat.size); // mediaLen
      framePack.setUint32(20, 683667402); //server_time
      framePack.setUint32(24, 0);
      framePack.setUint32(28, 0);
      framePack.setUint32(block - 4, steamByteLength);

      // console.log('statusPack', statusPack);
      if (this.channel && this.channel.isOpen()) {
        this.channel.sendMessageBinary(Buffer.from(framePack.buffer));
      }
      steamByteLength += data.byteLength;
    });
    steam.on('end', () => {
      steamByteLength = 0;
      // this.onSteaming = false;
    });
  }
}
