import 'dart:async';
import 'dart:convert';
import 'dart:js';

import 'package:crypto/crypto.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_web_plugins/flutter_web_plugins.dart';
import 'package:flutter_zoom_sdk/webSupport/zoom_js.dart';
import 'package:flutter_zoom_sdk/zoom_platform_view.dart';

import 'webSupport/js_interop.dart';
export 'package:flutter_zoom_sdk/zoom_platform_view.dart'
    show ZoomOptions, ZoomMeetingOptions;

/// Web Function For Zoom Sdk for Flutter Web Implementation
class ZoomViewWeb extends ZoomPlatform {
  StreamController<dynamic>? streamController;

  static void registerWith(Registrar registrar) {
    ZoomPlatform.instance = ZoomViewWeb();
  }

  /// Initialize Zoom SDK For Web
  @override
  Future<List> initZoom(ZoomOptions options) async {
    final Completer<List> completer = Completer();
    var sus = ZoomMtg.checkSystemRequirements();
    var susmap = convertToDart(sus);
    if (kDebugMode) {
      print(susmap);
    }

    ZoomMtg.i18n.load(options.language);
    ZoomMtg.preLoadWasm();
    ZoomMtg.prepareWebSDK();
    ZoomMtg.init(InitParams(
        leaveUrl: "/index.html",
        showMeetingHeader: options.showMeetingHeader,
        disableInvite: options.disableInvite,
        disableCallOut: options.disableCallOut,
        disableRecord: options.disableRecord,
        disableJoinAudio: options.disableJoinAudio,
        audioPanelAlwaysOpen: options.audioPanelAlwaysOpen,
        isSupportAV: options.isSupportAV,
        isSupportChat: options.isSupportChat,
        isSupportQA: options.isSupportQA,
        isSupportCC: options.isSupportCC,
        isSupportPolling: options.isSupportPolling,
        isSupportBreakout: options.isSupportBreakout,
        screenShare: options.screenShare,
        rwcBackup: options.rwcBackup,
        videoDrag: options.videoDrag,
        sharingMode: options.sharingMode,
        videoHeader: options.videoHeader,
        isLockBottom: options.isLockBottom,
        isSupportNonverbal: options.isSupportNonverbal,
        isShowJoiningErrorDialog: options.isShowJoiningErrorDialog,
        disablePreview: options.disablePreview,
        disableCORP: options.disableCORP,
        inviteUrlFormat: options.inviteUrlFormat,
        disableVoIP: options.disableVOIP,
        disableReport: options.disableReport,
        meetingInfo: options.meetingInfo,
        success: allowInterop((var res) {
          completer.complete([0, 0]);
        }),
        error: allowInterop((var res) {
          completer.complete([1, 0]);
        })));
    return completer.future;
  }

  /// Generate Signatue for zoom signate required to perform join and start functions
  String generateSignature(
      String apiKey, String apiSecret, String meetingNumber, int role) {
    final timestamp = DateTime.now().millisecondsSinceEpoch - 30000;
    var str = '$apiKey$meetingNumber$timestamp$role';
    var bytes = utf8.encode(str);
    final msg = base64.encode(bytes);

    final key = utf8.encode(apiSecret);
    final hmacSha256 = Hmac(sha256, key); // HMAC-SHA256
    final digest = hmacSha256.convert(utf8.encode(msg));
    final hash = base64.encode(digest.bytes);

    str = '$apiKey.$meetingNumber.$timestamp.$role.$hash';
    bytes = utf8.encode(str);
    final signature = base64.encode(bytes);
    return signature.replaceAll(RegExp("="), "");
  }

  /// Start Meeting Function for Zoom Web
  @override
  Future<List> startMeeting(ZoomMeetingOptions options) async {
    final Completer<List> completer = Completer();
    ZoomMtg.join(JoinParams(
        meetingNumber: options.meetingId,
        userName: options.displayName ?? options.userId,
        signature: options.jwtSignature!,
        apiKey: options.jwtAPIKey!,
        passWord: options.meetingPassword,
        success: allowInterop((var res) {
          completer.complete(["MEETING STATUS", "SUCCESS"]);
        }),
        error: allowInterop((var res) {
          completer.complete(["MEETING STATUS", "FAILED"]);
        })));
    return completer.future;
  }

  /// Join Meeting Function for Zoom Web
  @override
  Future<bool> joinMeeting(ZoomMeetingOptions options) async {
    final Completer<bool> completer = Completer();
    ZoomMtg.join(JoinParams(
        meetingNumber: options.meetingId,
        userName: options.displayName ?? options.userId,
        signature: options.jwtSignature!,
        apiKey: options.jwtAPIKey!,
        passWord: options.meetingPassword,
        success: allowInterop((var res) {
          completer.complete(true);
        }),
        error: allowInterop((var res) {
          completer.complete(false);
        })));
    return completer.future;
  }

  /// Listen to Ongoing Meeting Function for Zoom Web
  @override
  Future<List> meetingStatus(String meetingId) async {
    return ["a", "b"];
  }

  /// Meeting Status Response Function for Zoom Web
  @override
  Stream<dynamic> onMeetingStatus() {
    streamController?.close();
    streamController = StreamController<dynamic>();
    ZoomMtg.inMeetingServiceListener('onMeetingStatus', allowInterop((status) {
      var r = List<String>.filled(2, "");

      /// 1(connecting), 2(connected), 3(disconnected), 4(reconnecting)
      switch (status.meetingStatus) {
        case 1:
          r[0] = "MEETING_STATUS_CONNECTING";
          break;
        case 2:
          r[0] = "MEETING_STATUS_INMEETING";
          break;
        case 3:
          r[0] = "MEETING_STATUS_DISCONNECTING";
          break;
        case 4:
          r[0] = "MEETING_STATUS_INMEETING";
          break;
        default:
          r[0] = status.meetingStatus.toString();
          break;
      }
      streamController!.add(r);
    }));
    return streamController!.stream;
  }
}