//
//  react_native_amap_yf.m
//  react-native-amap-yf
//
//  Created by yf on 2018/3/5.
//  Copyright © 2018年 Classical_1956. All rights reserved.
//

#import "react_native_amap_yf.h"

#import <AMapLocationKit/AMapLocationKit.h>

#define DefaultLocationTimeout 10
#define DefaultReGeocodeTimeout 5
static react_native_amap_yf *_instance = nil;
static NSString *error_1 = @"-1001"; //没有权限
static NSString *error_2 = @"-1002"; //定位错误
static NSString *error_3 = @"-1003"; //逆地理错误
static NSString *error_4 = @"-1004"; //存在虚拟定位的风险
static NSString *error_5 = @"-1005"; //参数残缺

@interface react_native_amap_yf() <AMapLocationManagerDelegate>
@property (nonatomic, strong) AMapLocationManager *locationManager;
@property (nonatomic, copy) AMapLocatingCompletionBlock completionBlock;

@property (nonatomic, strong) RCTPromiseResolveBlock resolve_self;
@property (nonatomic, strong) RCTPromiseRejectBlock reject_self;

@property (nonatomic, strong) RCTPromiseResolveBlock resolve_regeocode;
@property (nonatomic, strong) RCTPromiseRejectBlock reject_regeocode;

@end

@implementation react_native_amap_yf

RCT_EXPORT_MODULE();


+ (instancetype)sharedInstance {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        if (_instance == nil) {
            _instance = [[self alloc] init];
        }
    });
    return _instance;
}
+ (instancetype)allocWithZone:(struct _NSZone *)zone{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        if (_instance == nil) {
            _instance = [super allocWithZone:zone];
        }
    });
    return _instance;
}
+ (dispatch_queue_t)sharedMethodQueue {
    static dispatch_queue_t methodQueue;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        methodQueue = dispatch_queue_create("com.yf.amaplocation", DISPATCH_QUEUE_SERIAL);
    });
    return methodQueue;
}
- (void)dealloc{
    self.completionBlock = nil;
    
}
- (dispatch_queue_t)methodQueue {
    return [react_native_amap_yf sharedMethodQueue];
}


- (AMapLocationManager *)locationManager{
    if (!_locationManager) {
        _locationManager = [[AMapLocationManager alloc] init];
        _locationManager.delegate = self;
        _locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters;
        _locationManager.pausesLocationUpdatesAutomatically = NO;
        _locationManager.allowsBackgroundLocationUpdates = NO;
        _locationManager.locationTimeout = DefaultLocationTimeout;
        _locationManager.reGeocodeTimeout = DefaultReGeocodeTimeout;
        _locationManager.detectRiskOfFakeLocation = NO;
        [self initCompletionBlock];
    }
    return _locationManager;
}

/**====================================================================================================================================================*/

- (void)initCompletionBlock{
    __weak react_native_amap_yf *weakSelf = self;
    self.completionBlock = ^(CLLocation *location, AMapLocationReGeocode *regeocode, NSError *error) {
        if (error != nil && error.code == AMapLocationErrorLocateFailed) {
            
            NSLog(@"定位错误 ： {%ld来的- %@}",(long)error.code,error.localizedDescription);
            if(weakSelf.reject_regeocode) weakSelf.reject_regeocode(error_2,@"定位错误", error);
            if(weakSelf.reject_self) weakSelf.reject_self(error_2, @"定位错误", error);
            return ;
        }else if (error != nil
                  && (error.code == AMapLocationErrorReGeocodeFailed
                      || error.code == AMapLocationErrorTimeOut
                      || error.code == AMapLocationErrorCannotFindHost
                      || error.code == AMapLocationErrorBadURL
                      || error.code == AMapLocationErrorNotConnectedToInternet
                      || error.code == AMapLocationErrorCannotConnectToHost))
        {
            //逆地理错误：在带逆地理的单次定位中，逆地理过程可能发生错误，此时location有返回值，regeocode无返回值，进行annotation的添加
            NSLog(@"逆地理错误:{%ld - %@};", (long)error.code, error.localizedDescription);
            
            if(weakSelf.reject_regeocode) weakSelf.reject_regeocode(error_3,@"逆地理错误", error);
            if(weakSelf.reject_self) weakSelf.reject_self(error_3, @"逆地理错误", error);
        }
        else if (error != nil && error.code == AMapLocationErrorRiskOfFakeLocation)
        {
            //存在虚拟定位的风险：此时location和regeocode没有返回值，不进行annotation的添加
            NSLog(@"存在虚拟定位的风险:{%ld - %@};", (long)error.code, error.localizedDescription);
            if(weakSelf.reject_regeocode) weakSelf.reject_regeocode(error_4,@"存在虚拟定位的风险", error);
            if(weakSelf.reject_self) weakSelf.reject_self(error_4, @"存在虚拟定位的风险", error);
            return;
        }else{
            //没有错误：location有返回值，regeocode是否有返回值取决于是否进行逆地理操作，进行annotation的添加
        }
        
        //修改label显示内容
        NSMutableDictionary *paramters = @{}.mutableCopy;
        [paramters setValue:@(location.coordinate.longitude) forKey:@"longitude"];
        [paramters setValue:@(location.coordinate.latitude) forKey:@"latitude"];
        
        if (regeocode)
        {
            NSLog(@"逆地理操作 =>, %@",[NSString stringWithFormat:@"%@ \n %@-%@-%.2fm", regeocode.formattedAddress,regeocode.citycode, regeocode.adcode, location.horizontalAccuracy]);
            
            [paramters setValue:regeocode.country forKey:@"country"];
            [paramters setValue:regeocode.province forKey:@"province"];
            [paramters setValue:regeocode.city forKey:@"city"];
            [paramters setValue:regeocode.citycode forKey:@"citycode"];
            [paramters setValue:regeocode.district forKey:@"district"];
            [paramters setValue:regeocode.adcode forKey:@"adcode"];
            [paramters setValue:regeocode.street forKey:@"street"];
            
            if (weakSelf.resolve_regeocode) weakSelf.resolve_regeocode(paramters);
            
        }
        else
        {
            NSLog(@"常规操作 => ,%@",[NSString stringWithFormat:@"lat:%f;lon:%f \n accuracy:%.2fm", location.coordinate.latitude, location.coordinate.longitude, location.horizontalAccuracy]);
            if(weakSelf.resolve_self) weakSelf.resolve_self(paramters);
        }
        
    };
}


/**
 *  开始基本位置定位
 */
RCT_REMAP_METHOD(startLocation,
                 resolver:(RCTPromiseResolveBlock)resolve
                 rejecter:(RCTPromiseRejectBlock)reject
                 ){
    self.resolve_self =  resolve;
    self.reject_self = reject;
    if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusDenied) {
        self.reject_self(error_1, @"没有定位权限", nil);
    }else{
        [self.locationManager requestLocationWithReGeocode:NO completionBlock:self.completionBlock];
    }
}

/** ==================================================================================================================================================== */


@end
