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/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:sliding_sheet2/sliding_sheet2.dart';
import '../../data/bean/user_info.dart';
import '../../dialog/location_permission_dialog.dart';
import '../../sdk/map/map_helper.dart';
import '../../utils/permission_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 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 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();
    _recordNumberTrajectoryViewed();
  }

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

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

  ///记录查看轨迹的次数
  void _recordNumberTrajectoryViewed() {
    if (accountRepository.memberStatusInfo.value?.trialed == true &&
        accountRepository.memberStatusInfo.value?.level == 20) {
      trackRepository.refreshMemberTrailTrack();
    }
  }

  ///显示轨迹以及标记点
  void showMapTrack(List<LatLng> points, List<Marker> markers) {
    mapController.clear();
    //画折线
    if (points.length > 1) {
      mapController.addPolyline(Constants.traceNormalLineId, 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(Constants.traceSelectLineId, movingPoints,
        lineType: PolylineType.selected, mapPadding: mapPadding);
  }

  void showTrackError(List<LatLng> errorPoints, Marker errorMarker) {
    _clearSelectMapMarker();
    mapController.updateOrAddMarker(errorMarker);
    mapController.addPolyline(Constants.traceSelectLineId, 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;
  }

  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();
    }
  }

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

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