import 'package:fis_common/index.dart';
import 'package:fis_i18n/i18n.dart';
import 'package:fis_jsonrpc/services/index.dart';
import 'package:flutter/material.dart';
import 'package:flyinsono/architecture/router/desktop/names.dart';
import 'package:flyinsono/architecture/router/router.dart';
import 'package:flyinsono/architecture/services/entity/local_setting.dart';
import 'package:flyinsono/architecture/states/states.dart';
import 'package:flyinsono/architecture/utils/prompt_box.dart';
import 'package:flyinsono/architecture/utils/web_parameter_helpler.dart';
import 'package:flyinsono/rpc.dart';
import 'package:flyinsono/views/common/device_live/device_live_detail/controller.dart';
import 'package:flyinsono/views/common/device_live/device_live_detail/state.dart';
import 'package:intl/intl.dart';

import 'state.dart';
import 'widgets/recorder.dart';

class DeviceLiveDetailDesktopController extends DeviceLiveDetailController {
  @override
  final DeviceLiveDetailDesktopState state = DeviceLiveDetailDesktopState();

  /// 窗口录制控制器(仅桌面)
  WindowRecorderController? windowRecorderController;
  bool _locking = false;

  @override
  void onInit() {
    super.onInit();
    _initParameters();
    state.maxLiveCount = Store.user.deviceLiveMaxCount;
    _initWindowRecorder();
  }

  /// 处理设备选中
  ///
  /// [isChecked] 是否选中
  ///
  /// [index] 索引
  Future<void> handleDeviceChecked(bool isChecked, int index) async {
    final model = state.deviceList[index];
    final code = model.dto.deviceCode!;

    if (isChecked == model.isChecked) {
      return;
    }

    if (isChecked) {
      if (_locking) return;
      _lock();

      if (state.maxLiveCount == 1) {
        if (state.liveIndexList.isNotEmpty) {
          // 只能保持一个，关掉前一个
          await handleDeviceChecked(false, state.liveIndexList[0]);
        }
      } else {
        if (!state.canShowMoreLive || _checkOverBrowserStreamLimit(model)) {
          // 超出最大限制直播数量
          PromptBox.toast(i18nBook.live.limitOfMaxLiveSourceCount.t);
          return _unlock();
        }
      }
      try {
        final liveInfo = await deviceManager.enterLiveRoom(code);
        if (liveInfo != null) {
          model.liveInfo = liveInfo;
          model.isChecked = true;
          state.liveIndexList.add(index);
        } else {
          _unlock();
          // 避开cancelBusy, 让全局报错正常显示
          return;
        }
      } catch (e) {
        PromptBox.error(i18nBook.common.networkInstability.t);
      }
      cancelBusy();
      _unlock();
    } else {
      await deviceManager.exitLiveRoom(code);
      model.isChecked = false;
      state.liveIndexList.removeWhere((e) => e == index);
    }
  }

  /// 根据code查找当前索引位置
  int findIndexByCode(String code) {
    return state.deviceList.indexWhere((e) => e.dto.deviceCode == code);
  }

  /// 检查设置直播设备状态
  ///
  /// remarks: 1表示正常，0表示失败；2表示需要重载webview
  Future<int> checkLiveDeviceState(String code) async {
    try {
      final info = (await deviceManager.getDeviceInfo(code))!;

      final index = findIndexByCode(code);
      final model = state.deviceList[index];

      // 直播信息变更or不在直播中
      // 重新进入直播
      final liveInfo = await deviceManager.enterLiveRoom(code);
      if (liveInfo != null) {
        // 进入直播成功
        // 更新设备和直播信息
        model.dto = info;
        model.liveInfo = liveInfo;
        return 2; // 通知webview reload
      }
    } catch (e) {
      //
    }
    return 0;
  }

  /// 检查是否超过浏览器直播流限制
  ///
  /// [device] 即将开始直播的设备
  bool _checkOverBrowserStreamLimit(DeviceStateModel device) {
    int streamCount = 0;
    for (var device in state.deviceList) {
      if (device.isChecked) {
        streamCount += _calcLiveUrlCount(device);
      }
    }
    streamCount += _calcLiveUrlCount(device);
    return streamCount > 6;
  }

  int _calcLiveUrlCount(DeviceStateModel model) {
    if (model.dto.mergedChannel) {
      return 1;
    }

    return model.dto.videoDeviceInfos?.length ?? 0;
  }

  @override
  Future<void> reloadList() async {
    final map = <String, bool>{};
    for (var index in state.liveIndexList) {
      final model = state.deviceList[index];
      map[model.dto.deviceCode!] = true;
    }
    await super.reloadList();
    state.liveIndexList.clear();
    for (var i = 0; i < state.deviceList.length; i++) {
      final model = state.deviceList[i];
      if (map[model.dto.deviceCode!] == true) {
        state.liveIndexList.add(i);
      }
    }
  }

  /// 开启窗口录制
  Future<void> startWinRecord() async {
    if (state.canRecordWindow) {
      windowRecorderController!.start();
      state.isWinRecordStarted = true;
    }
  }

  /// 结束窗口录制
  Future<void> stopWinRecord() async {
    if (state.canRecordWindow) {
      windowRecorderController!.stop();
      state.isWinRecordStarted = false;
    }
  }

  void _initWindowRecorder() async {
    if (state.canRecordWindow) {
      final hospitalName = Store.user.rootOrganizationName;
      final time = DateFormat('yyyyMMdd').format(DateTime.now()).toString();
      final title = "DeviceLiveRecord_${hospitalName}_$time";
      windowRecorderController = WindowRecorderController(title);
    }
  }

  /// 折叠列表面板
  void collapseListPanel() {
    state.isListPanelCollapsed = true;
  }

  /// 展开列表面板
  void expandListPanel() {
    state.isListPanelCollapsed = false;
  }

  @override
  Future<void> onAfterLoad() async {
    if (state.initialCode.isNotNullOrEmpty) {
      WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
        final index = state.deviceList
            .indexWhere((e) => e.dto.deviceCode == state.initialCode);
        if (index > -1) {
          handleDeviceChecked(true, index);
        }
      });
    }
  }

  @override
  void onClose() {
    _exitAllLives();
    super.onClose();
  }

  void _lock() => _locking = true;
  void _unlock() => _locking = false;

  void _exitAllLives() async {
    for (var index in state.liveIndexList) {
      final code = state.deviceList[index].dto.deviceCode!;
      deviceManager.exitLiveRoom(code);
    }
  }

  Future<void> _initParameters() async {
    Map<String, String> parameters;
    if (LocalSetting.ins.isUseSecondWindow == true) {
      parameters = ParameterHelper.parasmeters;
      if (parameters.containsKey("token") == false) {
        parameters = router.getParams() ?? {};
      }
    } else {
      parameters = router.getParams(NavIds.HOME) ?? {};
    }

    if (parameters.containsKey('code')) {
      state.initialCode = parameters['code'] ?? '';
    }

    Future.delayed(Duration(milliseconds: 1000), () {
      ParameterHelper.setWindowState();
    });
    if (parameters.containsKey('token')) {
      Store.user.setToken(parameters['token'] ?? '');
      final userInfo = await rpc.user.getUserInfoAsync(
        GetUserInfoRequest(token: Store.user.token),
      );
      Store.user.handleUserSyncUpdate(userInfo);
      final orgInfo = await rpc.organization
          .getOrganizationByCodeAsync(GetOrganizationByCodeRequest(
        token: Store.user.token,
        organizationCode: userInfo.rootOrganizationCode,
      ));
      Store.user.rootOrganizationName = orgInfo.organizationName ?? '';
    }
  }
}
