import 'dart:io';

import 'package:diplomaticquarterapp/config/shared_pref_kay.dart';
import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart';
import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart';
import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart';
import 'package:diplomaticquarterapp/uitl/utils.dart';
import 'package:diplomaticquarterapp/widgets/dialogs/confirm_dialog.dart';
import 'package:flutter/cupertino.dart';
import 'package:geolocator/geolocator.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:huawei_location/location/fused_location_provider_client.dart';
import 'package:huawei_location/location/location.dart';
import 'package:huawei_location/location/location_callback.dart';
import 'package:huawei_location/location/location_request.dart';
import 'package:huawei_location/location/location_settings_request.dart';
import 'package:huawei_location/permission/permission_handler.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:provider/provider.dart';

class LocationUtils {
  AppSharedPreferences sharedPref = new AppSharedPreferences();

  bool isShowConfirmDialog;
  BuildContext context;
  bool isHuawei;
  final GeolocatorPlatform _geolocatorPlatform = GeolocatorPlatform.instance;

  LocationUtils({@required this.isShowConfirmDialog, @required this.context, this.isHuawei = false});

  void getCurrentLocation({Function(LatLng) callBack}) async {
    if (Platform.isAndroid && isHuawei) {
      _getHMSCurrentLocation(callBack);
    } else {
      Geolocator.isLocationServiceEnabled().then((value) async {
        if (value) {
          await Geolocator.checkPermission().then((permission) async {
            if (permission == LocationPermission.always || permission == LocationPermission.whileInUse) {
              Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.low, timeLimit: Duration(seconds: 10)).then((value) {
                setLocation(value);
                if (callBack != null) callBack(LatLng(value.latitude, value.longitude));
              });
            }

            if (permission == LocationPermission.denied || permission == LocationPermission.deniedForever) {
              if (Platform.isAndroid) {
                Utils.showPermissionConsentDialog(context, TranslationBase.of(context).locationPermissionDialog, () async {
                  final hasPermission = await _handlePermission();
                  if (hasPermission) {
                    Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.medium, timeLimit: Duration(seconds: 10)).then((value) {
                      setLocation(value);
                      if (callBack != null) callBack(LatLng(value.latitude, value.longitude));
                    });
                  } else {
                    if (isShowConfirmDialog) showErrorLocationDialog(false);
                  }
                });
              } else {
                if (await Permission.location.request().isGranted) {
                  getCurrentLocation(callBack: callBack);
                } else {
                  setZeroLocation();
                  if (isShowConfirmDialog) showErrorLocationDialog(false);
                }
              }
            }
          }).catchError((err) {
            print(err);
          });
        } else {
          if (isShowConfirmDialog) showErrorLocationDialog(false);
        }
      }).catchError((err) {
        print(err);
      });
    }
  }

  Future<bool> _handlePermission() async {
    bool serviceEnabled;
    LocationPermission permission;

    serviceEnabled = await _geolocatorPlatform.isLocationServiceEnabled();
    if (!serviceEnabled) {
      return false;
    }

    permission = await _geolocatorPlatform.checkPermission();
    if (permission == LocationPermission.denied) {
      permission = await _geolocatorPlatform.requestPermission();
      if (permission == LocationPermission.denied) {
        return false;
      }
    }

    if (permission == LocationPermission.deniedForever) {
      return false;
    }
    return true;
  }

  LocationCallback _locationCallback;

  _getHMSCurrentLocation(Function(LatLng) callBack) async {
    PermissionHandler permissionHandler = PermissionHandler();

    int _locationUpdateCbId = 0;
    doIt() {
      FusedLocationProviderClient locationService = FusedLocationProviderClient();
      LocationRequest locationRequest = LocationRequest();
      locationRequest.priority = LocationRequest.PRIORITY_HIGH_ACCURACY;
      locationRequest.interval = 1000;
      List<LocationRequest> locationRequestList = <LocationRequest>[locationRequest];
      LocationSettingsRequest locationSettingsRequest = LocationSettingsRequest(requests: locationRequestList);

      locationService.checkLocationSettings(locationSettingsRequest).then((settings) async {
        _locationUpdateCbId = await locationService.requestLocationUpdatesCb(
            locationRequest,
            LocationCallback(onLocationResult: (locationResult) {
              Location location = locationResult.lastLocation;
              locationService.removeLocationUpdatesCb(_locationUpdateCbId);
              callBack(LatLng(location.latitude, location.longitude));
              setLocation(Position(latitude: location.latitude, longitude: location.longitude, altitude: location.altitude));
            }, onLocationAvailability: (locationAvailability) {
              print("onLocationAvailability: $locationAvailability");
            }));
      }).catchError((error) {
        if (error.code == "LOCATION_SETTINGS_NOT_AVAILABLE") {
          // Location service not enabled.
        }
      });
    }

    if (await permissionHandler.hasLocationPermission()) {
      doIt();
    } else {
      bool has = await requestPermissions();
      if (has)
        doIt();
      else if (isShowConfirmDialog) showErrorLocationDialog(false);
    }
  }

  showErrorLocationDialog(bool isPermissionError) {
    ConfirmDialog dialog = new ConfirmDialog(
        context: context,
        confirmMessage: TranslationBase.of(context).locationDialogMessage,
        okText: TranslationBase.of(context).confirm,
        cancelText: TranslationBase.of(context).cancel_nocaps,
        okFunction: () => {ConfirmDialog.closeAlertDialog(context), if (isPermissionError) Geolocator.openAppSettings() else Geolocator.openLocationSettings(), Navigator.of(context).canPop()},
        cancelFunction: () => {});
    return dialog.showAlertDialog(context);
  }

  void setLocation(Position position) {
    this.sharedPref.setDouble(USER_LAT, position != null ? position.latitude : 0.0);
    this.sharedPref.setDouble(USER_LONG, position != null ? position.longitude : 0.0);
    ProjectViewModel projectViewModel = Provider.of(context, listen: false);
    projectViewModel.setLatitudeLongitude(position.latitude, position.longitude);
  }

  void setZeroLocation() {
    this.sharedPref.setDouble(USER_LAT, 0.0);
    this.sharedPref.setDouble(USER_LONG, 0.0);
  }

  Future<bool> requestPermissions() async {
    var result = await [
      Permission.location,
    ].request();
    return (result[Permission.location].isGranted || result[Permission.locationAlways].isGranted);
  }
}
