//
/***************************************************************
 * Copyright © 2017 HERE Global B.V. All rights reserved. *
 **************************************************************/

#import <Foundation/Foundation.h>
#import "HereSDKDemand.h"
#import <React/RCTLog.h>

#import "HereSDKDemandRide+Dictionary.h"
#import "HereSDKDemandTaxiRideOffer+Dictionary.h"
#import "HereSDKDemandPublicTransportRideOffer+Dictionary.h"
#import "HereSDKDemandQueryRidesResponse+Dictionary.h"
#import "HereSDKDemandRideStatusLog+Dictionary.h"
#import "HereSDKDemandRideLocation+Dictionary.h"
#import "HereSDKDemandCancellationInfo+Dictionary.h"
#import "HereSDKDemandRideQuery+JSDictionary.h"
#import "HereSDKDemandRideOffersRequest+JSDictionary.h"
#import "RCTConvert+HereSDKDemandRidePreferences.h"
#import "RCTConvert+HereSDKDemandPassenger.h"

#import "NSString+Utilities.h"
#import "NSError+Dictionary.h"

@implementation HereSDKDemand

RCT_EXPORT_MODULE();
RCT_EXPORT_METHOD(getRideOffers:(NSDictionary *)rideOffersParams
                  cb:(RCTResponseSenderBlock)cb) {
    
    HereSDKDemandRideOffersRequest *request = [HereSDKDemandRideOffersRequest requestFromJSParams:rideOffersParams];
    [HereSDKDemandManager.sharedManager requestRide:request withHandler:^(NSArray<id<HereSDKDemandRideOfferProtocol>> * _Nullable offers, NSError * _Nullable error) {
        if (error != NULL)
        {
            cb(@[[NSNull null], [NSString hereSDK_jsonFromObject:error.dictionary]]);
        }
        else
        {
            NSMutableArray *offersArr = [NSMutableArray new];
            for (id<HereSDKDemandRideOfferProtocol> offer in offers)
            {
                switch (offer.getTransitType)
                {
                    case HereSDKDemandTransitTypeTaxi:
                        [offersArr addObject: ((HereSDKDemandTaxiRideOffer *)offer).dictionary];
                        break;
                    case HereSDKDemandTransitTypePublicTransport:
                        [offersArr addObject: ((HereSDKDemandPublicTransportRideOffer *)offer).dictionary];
                        break;
                }
            }
            
            NSString *offersJson = [NSString hereSDK_jsonFromObject:offersArr];
            cb(@[offersJson, [NSNull null]]);
        }
    }];
}

RCT_EXPORT_METHOD(createRide:(NSString *)offerId
                  passengerDetails:(NSDictionary *)passengerDetails
                  ridePreferences:(NSDictionary *)ridePreferences
                  cb:(RCTResponseSenderBlock)cb) {

    HereSDKDemandPassenger *passenger = [RCTConvert HereSDKDemandPassenger:passengerDetails];
    HereSDKDemandRideRequest *req = [HereSDKDemandRideRequest
                                     rideRequestWithOfferId:offerId
                                     passengerDetails:passenger
                                     ridePreferences:ridePreferences ? [RCTConvert HereSDKDemandRidePreferences:ridePreferences] : nil];

    [HereSDKDemandManager.sharedManager createRideWithRequest:req withHandler:^(HereSDKDemandRide * _Nullable ride, NSError * _Nullable error) {
        if (error != NULL) {
            cb(@[[NSNull null], [NSString hereSDK_jsonFromObject:error.dictionary]]);
        } else {
            NSString *rideJson = [NSString hereSDK_jsonFromObject:ride.dictionary];
            cb(@[rideJson, [NSNull null]]);
        }
    }];
}

/**
 * Note that params is nullable.
 */
RCT_EXPORT_METHOD(getRides:(NSDictionary*) params
                  cb:(RCTResponseSenderBlock)cb) {
    HereSDKDemandRideQuery *request = [HereSDKDemandRideQuery requestFromJSParams:params];
    [HereSDKDemandManager.sharedManager getRides:request withHandler:^(HereSDKDemandQueryRidesResponse * _Nonnull ridesResponse, NSError * _Nullable error) {
        if (error != NULL) {
            cb(@[[NSNull null], [NSString hereSDK_jsonFromObject:error.dictionary]]);
        } else {
            NSString *ridesJson = [NSString hereSDK_jsonFromObject:ridesResponse.dictionary];
            cb(@[ridesJson, [NSNull null]]);
        }
    }];
}

RCT_EXPORT_METHOD(cancelRide:(NSString *)rideId
                  reason:(NSString *)reason
                  cb:(RCTResponseSenderBlock)cb) {
    HereSDKDemandCancelRideRequest *cancelRequest = [HereSDKDemandCancelRideRequest cancelRideWithRideId:rideId cancelReason:reason];
    [HereSDKDemandManager.sharedManager cancelRideWithRequest:cancelRequest withHandler:^(HereSDKDemandCancellationInfo * _Nullable cancellationInfo, NSError * _Nullable error) {
        if (error != NULL) {
            cb(@[[NSNull null], [NSString hereSDK_jsonFromObject:error.dictionary]]);
        } else {
            NSString *cancellationJson = [NSString hereSDK_jsonFromObject:cancellationInfo.dictionary];
            cb(@[cancellationJson, [NSNull null]]);
        }
    }];
}

RCT_EXPORT_METHOD(getRide:(NSString *)rideId
                  cb:(RCTResponseSenderBlock)cb) {
    [HereSDKDemandManager.sharedManager getRideWithRequest:rideId withHandler:^(HereSDKDemandRide * _Nullable ride, NSError * _Nullable error) {
        if (error != NULL) {
            cb(@[[NSNull null], [NSString hereSDK_jsonFromObject:error.dictionary]]);
        } else {
            NSString *rideJson = [NSString hereSDK_jsonFromObject:ride.dictionary];
            cb(@[rideJson, [NSNull null]]);
        }
    }];
}

RCT_EXPORT_METHOD(registerForRidesUpdates) {
    [HereSDKDemandManager.sharedManager registerForRidesUpdatesWithDelegate:self];
}

RCT_EXPORT_METHOD(unregisterFromRidesUpdates) {
    [HereSDKDemandManager.sharedManager unregisterForRidesUpdates];
}

- (NSArray<NSString *> *)supportedEvents
{
    return @[@"ride_status_changed", @"ride_location_changed", @"ride_updates_error"];
}

#pragma mark - HereSDKDemandClientDelegate
- (void)didReceiveUpdate:(HereSDKDemandRideStatusLog *)statusLog forRide:(HereSDKDemandRide *)ride
{
    NSString *rideStatus =  [HereSDKDemandRideStatusUpdate recordStatusToString:statusLog.currentStatus];
    NSLog(@"[DemandLog] %@",[NSString stringWithFormat:@"ride[%@] status[%@]",ride.rideId,rideStatus]);
    NSDictionary *response = @{
                               @"ride":ride.dictionary,
                               @"rideStatusLog": statusLog.dictionary,
                               };
    NSString *jsonResponse = [NSString hereSDK_jsonFromObject:response];
    [self sendEventWithName:@"ride_status_changed" body:jsonResponse];
}

- (void)didReceiveLocation:(HereSDKDemandRideLocation *)location forRide:(HereSDKDemandRide *)ride
{
    NSLog(@"[DemandLog] %@",[NSString stringWithFormat:@"ride[%@] location[%f %f]",ride.rideId,location.vehicleLocation.coordinate.latitude, location.vehicleLocation.coordinate.longitude]);
    NSDictionary *response = @{
                               @"ride":ride.dictionary,
                               @"rideLocation": location.dictionary,
                               };
    NSString *jsonResponse = [NSString hereSDK_jsonFromObject:response];
    [self sendEventWithName:@"ride_location_changed" body:jsonResponse];
}

- (void)didReceiveUpdateError:(NSError *)error
{
    
}

@end


