import 'dart:io';

import 'package:diplomaticquarterapp/config/shared_pref_kay.dart';
import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart';
import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart';
import 'package:diplomaticquarterapp/widgets/dialogs/confirm_dialog.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_hms_gms_availability/flutter_hms_gms_availability.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';

class LocationUtils {
  AppSharedPreferences sharedPref = new AppSharedPreferences();

  bool isShowConfirmDialog;
  BuildContext context;

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

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

            if (permission == LocationPermission.denied || permission == LocationPermission.deniedForever) {
              if(await Permission.location.request().isGranted) {
                getCurrentLocation();
            } else {
                setZeroLocation();
                if (isShowConfirmDialog) showErrorLocationDialog(false);
              }
            }
          }).catchError((err) {
            print(err);
          });
        } else {
          if (isShowConfirmDialog) showErrorLocationDialog(false);
        }
      }).catchError((err) {
        print(err);
      });
    }
  }

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

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