#import <React/RCTBridgeModule.h>
#import <BaiduMapAPI_Search/BMKGeocodeSearch.h>
#import <BaiduMapAPI_Search/BMKSuggestionSearch.h>
#import <BaiduMapAPI_Search/BMKSearchComponent.h>
@interface RCTGeocodeModule : NSObject <RCTBridgeModule, BMKGeoCodeSearchDelegate ,BMKSuggestionSearchDelegate>
@end

@implementation RCTGeocodeModule {
    BMKGeoCodeSearch *_search;
    BMKSuggestionSearch *_sugSearch;
    RCTPromiseResolveBlock _resolve;
    RCTPromiseRejectBlock _reject;
}

RCT_EXPORT_MODULE(BaiduMapGeocode)

RCT_EXPORT_METHOD(search:(NSString *)address
                    city:(NSString *)city
      searchWithResolver:(RCTPromiseResolveBlock)resolve
                rejecter:(RCTPromiseRejectBlock)reject) {
    BMKGeoCodeSearchOption *option = [BMKGeoCodeSearchOption new];
    option.city = city;
    option.address = address;
    _resolve = resolve;
    _reject = reject;
    if (!_search) {
        _search = [BMKGeoCodeSearch new];
        _search.delegate = self;
    }
    [_search geoCode:option];
}

RCT_EXPORT_METHOD(suggestion:(NSString *)address
                  city:(NSString *)city
                  searchWithResolver:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject) {
    BMKSuggestionSearchOption *option = [BMKSuggestionSearchOption new];
    option.cityname = city;
    option.keyword = address;
    _resolve = resolve;
    _reject = reject;
    if (!_sugSearch) {
        _sugSearch = [BMKSuggestionSearch new];
        _sugSearch.delegate = self;
    }
    [_sugSearch suggestionSearch:option];
    
}

RCT_EXPORT_METHOD(reverse:(CLLocationCoordinate2D)coordinate
                 resolver:(RCTPromiseResolveBlock)resolve
                 rejecter:(RCTPromiseRejectBlock)reject) {
    BMKReverseGeoCodeOption *option = [BMKReverseGeoCodeOption new];
    option.reverseGeoPoint = coordinate;
    _resolve = resolve;
    _reject = reject;
    if (!_search) {
        _search = [BMKGeoCodeSearch new];
        _search.delegate = self;
    }
    [_search reverseGeoCode:option];
}


- (void)onGetSuggestionResult:(BMKSuggestionSearch *)searcher result:(BMKSuggestionResult *)result errorCode:(BMKSearchErrorCode)error{
    if (error == BMK_SEARCH_NO_ERROR) {
        NSMutableArray *array = [NSMutableArray array];
        for(int i = 0; i < result.keyList.count; i++){
            CLLocationCoordinate2D p;
            [result.ptList[i] getValue:&p];
            if (!isnan(p.longitude) && !isnan(p.latitude)) {
                NSDictionary *dict=@{@"city":result.cityList[i],@"key":result.keyList[i],@"pt":@{@"latitude":@(p.latitude),@"longitude":@(p.longitude)}};
                [array addObject:dict];
            }
        }
        
        NSData *jsonData = [NSJSONSerialization dataWithJSONObject:array options:0 error:nil];
        NSString *jsonStr = [[NSString alloc]initWithData:jsonData encoding:NSUTF8StringEncoding];
        jsonStr = [jsonStr stringByReplacingOccurrencesOfString:@"\\" withString:@""];
        
        _resolve(@{
                   @"suggestion": jsonStr
                   });
    } else {
        _reject(@"", @"", nil);
    }
}

- (void)onGetGeoCodeResult:(BMKGeoCodeSearch *)searcher result:(BMKGeoCodeResult *)result errorCode:(BMKSearchErrorCode)error {
    if (error == BMK_SEARCH_NO_ERROR) {
        _resolve(@{
            @"latitude": @(result.location.latitude),
            @"longitude": @(result.location.longitude),
            @"address": result.address,
        });
    } else {
        // TODO: provide error message
        _reject(@"", @"", nil);
    }
}

- (void)onGetReverseGeoCodeResult:(BMKGeoCodeSearch *)searcher
                           result:(BMKReverseGeoCodeResult *)result
                        errorCode:(BMKSearchErrorCode)error {
    
    if (error == BMK_SEARCH_NO_ERROR) {
        
        NSLog(@"poiList===%@",result.poiList);
        
        NSMutableArray *array=[NSMutableArray array];
        
        for (BMKPoiInfo *pointInfo in result.poiList) {
            NSDictionary *dict=@{@"address":pointInfo.address,@"city":pointInfo.city,@"location":@{@"latitude":@(pointInfo.pt.latitude),@"longitude":@(pointInfo.pt.longitude)},@"name":pointInfo.name};
            [array addObject:dict];
        }
        
        NSData *jsonData = [NSJSONSerialization dataWithJSONObject:array options:0 error:nil];
        NSString *jsonStr = [[NSString alloc]initWithData:jsonData encoding:NSUTF8StringEncoding];
        jsonStr = [jsonStr stringByReplacingOccurrencesOfString:@"\\" withString:@""];
        
        _resolve(@{
            @"latitude": @(result.location.latitude),
            @"longitude": @(result.location.longitude),
            @"country": result.addressDetail.country,
            @"countryCode": result.addressDetail.countryCode,
            @"province": result.addressDetail.province,
            @"city": result.addressDetail.city,
            @"cityCode": result.cityCode,
            @"street": result.addressDetail.streetName,
            @"streetNumber": result.addressDetail.streetNumber,
            @"adCode": result.addressDetail.adCode,
            @"businessCircle": result.businessCircle,
            @"address": result.address,
            @"description": result.sematicDescription,
            @"poiList": jsonStr
        });
    } else {
        // TODO: provide error message
        _reject(@"", @"", nil);
    }
}

@end
