import 'package:flutter/material.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:get/get_core/src/get_main.dart';
import 'package:injectable/injectable.dart';
import 'package:location/base/base_controller.dart';
import 'package:location/data/api/response/track_daily_summary_response.dart';
import 'package:location/data/bean/track_days.dart';
import 'package:location/data/consts/constants.dart';
import 'package:location/data/repositories/account_repository.dart';
import 'package:location/data/repositories/friends_repository.dart';
import 'package:location/data/repositories/track_repository.dart';
import 'package:location/handler/error_handler.dart';
import 'package:location/resource/string.gen.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:sliding_sheet2/sliding_sheet2.dart';
import '../../data/bean/track_daily_bean.dart';
import '../../data/bean/user_info.dart';
import '../../dialog/common_confirm_dialog_impl.dart';
import '../../dialog/loading_dialog.dart';
import '../../dialog/location_permission_dialog.dart';
import '../../sdk/map/map_helper.dart';
import '../../sdk/wechat/wechat_share_util.dart';
import '../../utils/permission_util.dart';
import '../../utils/toast_util.dart';

@injectable
class TrackController extends BaseController
    with GetSingleTickerProviderStateMixin {
  final Rxn<UserInfo> _userInfo = Rxn<UserInfo>();

  UserInfo? get userInfo => _userInfo.value;

  final MapController mapController = MapController();

  SheetController sheetController = SheetController();

  final RxList<TrackDays> daysList = RxList<TrackDays>();

  final Rxn<TabController> _tabController = Rxn<TabController>();

  TabController? get tabController => _tabController.value;

  final Rxn<TrackDays> currentTrackDay = Rxn();

  final GlobalKey shareGlobalKey = GlobalKey();

  final RxDouble _sheetProgress = 0.0.obs;

  double get sheetProgress => _sheetProgress.value;

  final mapPadding =
      MapPadding(left: 50.w, top: 100.w, right: 50.w, bottom: Get.height / 2);

  final selectPadding =
      MapPadding(left: 80.w, top: 150.w, right: 80.w, bottom: Get.height / 2);

  final RxDouble trackBottomHeight = RxDouble(330.w);

  final Rxn<TrackDailySummaryResponse> _shareTrackData = Rxn();

  TrackDailySummaryResponse? get shareTrackData => _shareTrackData.value;

  TrackDailyBean? selectedTrackDailyBean;

  final TrackRepository trackRepository;
  final FriendsRepository friendsRepository;
  final AccountRepository accountRepository;

  TrackController(
      this.trackRepository, this.friendsRepository, this.accountRepository);

  @override
  void onInit() {
    final param = Get.arguments;
    if (param is UserInfo) {
      _userInfo.value = param;
    }
    _onRequestTrackDateList();
  }

  @override
  void onReady() {
    super.onReady();
    sheetController.expand();
  }

  void _onRequestTrackDateList() {
    trackRepository.getLocationTrackDays().then((list) {
      daysList.assignAll(list);
      _createTabController();
    }).catchError((error) {
      ErrorHandler.toastError(error);
    });
  }

  void _createTabController() {
    tabController?.dispose();
    var inintIndex = 0;
    if (_userInfo.value?.isShowYesterday ?? false) {
      //控制请求当前页数据或者数据已有时跟换数据
      inintIndex = 1;
    }
    final tab = TabController(
      length: daysList.length,
      vsync: this,
      initialIndex: inintIndex,
    );
    _tabController.value = tab;
    tab.addListener(() {
      if (tab.indexIsChanging == false) {
        //控制请求当前页数据或者数据已有时跟换数据
        mapController.clear();
        selectedTrackDailyBean = null;
        currentTrackDay.value = daysList[tab.index];
      }
    });
    Future.delayed(Duration(milliseconds: 100), () {
      if (_userInfo.value?.isShowYesterday ?? false) {
        //控制请求当前页数据或者数据已有时跟换数据
        if (daysList.length > 1) {
          currentTrackDay.value = daysList.isNotEmpty ? daysList[1] : null;
        }
      } else {
        currentTrackDay.value = daysList.isNotEmpty ? daysList[0] : null;
      }
    });
  }

  ///显示轨迹以及标记点
  void showMapTrack(List<LatLng> points, List<Marker> markers) {
    mapController.clear();
    //画折线
    if (points.length > 1) {
      mapController.addPolyline(
          Polyline(lineId: Constants.traceNormalLineId, points: points),
          mapPadding: mapPadding);
    }
    //画标记点
    if (markers.isNotEmpty) {
      mapController.updateOrAddMarkers(markers);
    }
  }

  void showSelectMarker(List<LatLng> points, Marker selectMarker) {
    clearSelectMapMarker();
    mapController.updateOrAddMarker(selectMarker);
    mapController.moveToSuitableLocation(points, mapPadding: selectPadding);
  }

  void back() {
    Get.back();
  }

  void showMovingTrack(List<LatLng> movingPoints) {
    clearSelectMapMarker();
    mapController.addPolyline(
        Polyline(
            lineId: Constants.traceSelectLineId,
            points: movingPoints,
            lineType: PolylineType.selected),
        mapPadding: mapPadding);
  }

  void showTrackError(List<LatLng> errorPoints, Marker errorMarker) {
    clearSelectMapMarker();
    mapController.updateOrAddMarker(errorMarker);
    mapController.addPolyline(
        Polyline(
            lineId: Constants.traceSelectLineId,
            points: errorPoints,
            lineType: PolylineType.error),
        mapPadding: mapPadding);
  }

  void clearSelectMapMarker() {
    mapController.removeMarker(Constants.mineLocationId);
    mapController.removePolyline(Constants.traceSelectLineId);
    mapController.removeMarker(Constants.tracePopupId);
    mapController.removeMarker(Constants.traceErrorId);
  }

  setSheetProgress(double progress) {
    _sheetProgress.value = progress;
    if (progress >= 1) {
      trackBottomHeight.value = 0;
    } else if (progress <= 0.45) {
      trackBottomHeight.value = 330.w;
    } else {
      double percent = (1 - progress) / (1 - 0.45);
      trackBottomHeight.value = 330.w * percent;
    }
  }

  void onCurrentLocationClick() async {
    //权限检查
    bool isGranted = await PermissionUtil.checkLocationPermission();
    if (!isGranted) {
      LocationPermissionDialog.show(onNextStep: _requestLocationPermission);
    } else {
      _updateCurrentLocation();
    }
  }

  void _updateCurrentLocation() {
    var lastLocation = MapHelper.getLastLocation();
    if (lastLocation == null) {
      locationListener(MapLocation location) {
        MapHelper.removeLocationListener(locationListener);
        showMineLocationMarker(location);
      }

      MapHelper.addLocationListener(locationListener);
    } else {
      showMineLocationMarker(lastLocation);
    }
  }

  void showMineLocationMarker(MapLocation location) {
    clearSelectMapMarker();
    Marker mineMarker = Marker(
        id: Constants.mineLocationId,
        latitude: location.latitude,
        longitude: location.longitude,
        isSelected: false,
        customAvatarUrl: accountRepository.mineUserInfo.value.avatar,
        markerName: StringName.locationMine,
        markerType: MarkerType.mine);
    mapController.updateOrAddMarker(mineMarker);
    animateCamera(latitude: location.latitude, longitude: location.longitude);
  }

  void animateCamera({required double? latitude, required double? longitude}) {
    mapController.animateCamera(
        CameraPosition(longitude: longitude, latitude: latitude, zoom: 18));
  }

  void _requestLocationPermission() async {
    bool isGranted = await PermissionUtil.requestLocationPermission();
    if (isGranted) {
      _showLocationAlways();
      _updateCurrentLocation();
    } else {
      permissionRefuseDialog(settingClick: () {
        openAppSettings();
      });
      ToastUtil.show(StringName.permissionRequestFail);
    }
  }

  void _showLocationAlways() async {
    bool isGranted = await PermissionUtil.checkShowLocationAlways();
    if (!isGranted) {
      LocationAlwaysPermissionDialog.show(onNextStep: () async {
        isGranted = await PermissionUtil.requestShowLocationAlways();
        if (isGranted) {
          _updateCurrentLocation();
        }
      });
    }
  }

  void shareTrack(TrackDailySummaryResponse summary) async {
    final day = currentTrackDay.value;
    final userInfo = _userInfo.value;
    if (day == null || userInfo == null) {
      return;
    }
    try {
      CustomLoadingDialog.show();
      _shareTrackData.value = summary;
      await Future.delayed(Duration(milliseconds: 500));
      await WechatShareUtil.shareWidgetToWeChat(shareGlobalKey);
    } catch (e) {
      print(e);
    }
    CustomLoadingDialog.hide();
    _shareTrackData.value = null;
  }

  @override
  void onClose() {
    super.onClose();
    tabController?.dispose();
  }
}
