import 'dart:async';
import 'dart:math';

import 'package:application/logger.dart';
import 'package:common_pub/model/history_detail.dart';
import 'package:application/service/api.dart';
import 'package:application/service/map_watch.dart';
import 'package:common_pub/ui/history_detail/trace_bar.dart';
import 'package:common_pub/ui/map_view/view_map_cp.dart';
import 'package:common_pub/ui/map_view/view_map_trace.dart';
import 'package:fixnum/fixnum.dart';
import 'package:get/get.dart';
import '../home_controller.dart';
export 'package:application/service/map_watch.dart';

class UserInfo {
  var data = ToHisUserBasic();
  final isExpand = false.obs;
}

typedef DetailSimple = ToHisUserInfo;

class Detail {
  var data = ToGameDetailReply();
}

class DataDetailController extends GetxController {
  HomeController get _home => Get.find();
  MapWatchService? get mapWatch => MapWatchService.instance;
  final userMap = <int, UserInfo>{}.obs;
  Iterable<UserInfo> get userList => userMap.values;
  final selectedDetailSimple = DetailSimple().obs;
  final selectedUserId = (-9).obs;
  final Rx<HistoryDetail?> selectedDetail = Rx(null);
  final stub = ApiService.to.stub;
  final showDetail = false.obs;
  final isCPExpand = true.obs;
  final traceBarController = TraceBarController();
  final viewMapTraceController = ViewMapTraceController();
  StreamSubscription<int?>? _subscriptionTrace;
  final selectedLoading = false.obs;
  final viewCPController = ViewMapCPController();

  @override
  void onInit() {
    super.onInit();
    _subscriptionTrace = traceBarController.cursorState.listen((p0) {
      viewMapTraceController.cursor = p0;
    });
    workFlush();
  }

  Future<void> workFlush() async {
    while (!isClosed) {
      await flushData();
      await 1.seconds.delay();
    }
  }

  Future<void> flushData() async {
    final map = mapWatch;
    if (map == null) {
      return;
    }

    try {
      final t = DateTime.now();
      final r = await ApiService.to.stub
          .toHistoryUserListQuery(IdRequest(id: map.id));
      final d = DateTime.now().difference(t);
      // debug('api cost $d');
      for (final one in r.list) {
        final updated = userMap[one.oId] ?? UserInfo();
        updated.data = one;
        userMap[one.oId] = updated;
      }
    } catch (e) {
      error(e);
    }
  }

  void selectDetail(DetailSimple d, UserInfo user) async {
    selectedDetailSimple.value = d;
    selectedUserId.value = user.data.oId;
    selectedLoading.value = true;
    try{
      final t = DateTime.now();
      final detail = HistoryDetail(await ApiService.to.stub
          .toHistoryGameDetail(IdRequest(id: Int64(d.gameId))));
      final cost = DateTime.now().difference(t);
      info("api cost $cost");

      await detail.init(mapWatch!.plugMap.gameMap);
      final old = selectedDetail.value;
      selectedDetail.value = detail;
      debug('select: ${detail.data.gameId}');
      if (old != null) {
        old.dispose();
      }
    }finally{
      selectedLoading.value = false;
    }

  }

  @override
  void onClose() {
    super.onClose();
    _subscriptionTrace?.cancel();
  }
}
