/*
 * Version for React Native
 * © 2020 YANDEX
 * You may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * https://yandex.com/legal/appmetrica_sdk_agreement/
 */

#import "AppMetricaUtils.h"

@implementation AppMetricaUtils

+ (AMAAppMetricaConfiguration *)configurationForDictionary:(NSDictionary *)configDict
{
    NSString *apiKey = configDict[@"apiKey"];
    AMAAppMetricaConfiguration *configuration = [[AMAAppMetricaConfiguration alloc] initWithAPIKey:apiKey];

    if (configDict[@"appVersion"] != nil) {
        configuration.appVersion = configDict[@"appVersion"];
    }
    if (configDict[@"activationAsSessionStart"] != nil) {
        configuration.handleActivationAsSessionStart = [configDict[@"activationAsSessionStart"] boolValue];
    }
    if (configDict[@"firstActivationAsUpdate"] != nil) {
        configuration.handleFirstActivationAsUpdate = [configDict[@"firstActivationAsUpdate"] boolValue];
    }
    if (configDict[@"location"] != nil) {
        configuration.customLocation = [self locationForDictionary:configDict[@"location"]];
    }
    if (configDict[@"locationTracking"] != nil) {
        configuration.locationTracking = [configDict[@"locationTracking"] boolValue];
    }
    if (configDict[@"accurateLocationTracking"] != nil) {
        configuration.accurateLocationTracking = [configDict[@"accurateLocationTracking"] boolValue];
    }
    if (configDict[@"allowsBackgroundLocationUpdates"] != nil) {
        configuration.allowsBackgroundLocationUpdates = [configDict[@"allowsBackgroundLocationUpdates"] boolValue];
    }
    if (configDict[@"logs"] != nil) {
        configuration.logsEnabled = [configDict[@"logs"] boolValue];
    }
    if (configDict[@"preloadInfo"] != nil) {
        configuration.preloadInfo = [[self class] preloadInfoForDictionary:configDict[@"preloadInfo"]];
    }
    if (configDict[@"sessionsAutoTrackingEnabled"] != nil) {
        configuration.sessionsAutoTracking = [configDict[@"sessionsAutoTrackingEnabled"] boolValue];
    }
    if (configDict[@"sessionTimeout"] != nil) {
        configuration.sessionTimeout = [configDict[@"sessionTimeout"] unsignedIntegerValue];
    }
    if (configDict[@"dataSendingEnabled"] != nil) {
        configuration.dataSendingEnabled = [configDict[@"dataSendingEnabled"] boolValue];
    }
    if (configDict[@"revenueAutoTrackingEnabled"] != nil) {
        configuration.revenueAutoTrackingEnabled = [configDict[@"revenueAutoTrackingEnabled"] boolValue];
    }
    if (configDict[@"appOpenTrackingEnabled"] != nil) {
        configuration.appOpenTrackingEnabled = [configDict[@"appOpenTrackingEnabled"] boolValue];
    }
    if (configDict[@"appBuildNumber"] != nil) {
        configuration.appBuildNumber = configDict[@"appBuildNumber"];
    }
    if (configDict[@"userProfileID"] != nil) {
        configuration.userProfileID = configDict[@"userProfileID"];
    }
    if (configDict[@"dispatchPeriodSeconds"] != nil) {
        configuration.dispatchPeriod = [configDict[@"dispatchPeriodSeconds"] unsignedIntegerValue];
    }
    if (configDict[@"maxReportsCount"] != nil) {
        configuration.maxReportsCount = [configDict[@"maxReportsCount"] unsignedIntegerValue];
    }
    if (configDict[@"maxReportsInDatabaseCount"] != nil) {
        configuration.maxReportsInDatabaseCount = [configDict[@"maxReportsInDatabaseCount"] unsignedIntegerValue];
    }
    if (configDict[@"customHosts"] != nil) {
        configuration.customHosts = [configDict valueForKey:@"customHosts"];
    }
    if (configDict[@"appEnvironment"] != nil) {
        configuration.appEnvironment = configDict[@"appEnvironment"];
    }

    return configuration;
}

+ (AMAAppMetricaCrashesConfiguration *)crashesConfigurationForDictionary:(NSDictionary *)configDict
{
    AMAAppMetricaCrashesConfiguration *configuration = [[AMAAppMetricaCrashesConfiguration alloc] init];

    if (configDict[@"crashReporting"] != nil) {
        configuration.autoCrashTracking = [configDict[@"crashReporting"] boolValue];
    }
    if (configDict[@"anrMonitoring"] != nil) {
        configuration.applicationNotRespondingDetection = [configDict[@"anrMonitoring"] boolValue];
    }
    if (configDict[@"anrMonitoringTimeout"] != nil) {
        configuration.applicationNotRespondingWatchdogInterval = [configDict[@"anrMonitoringTimeout"] unsignedIntegerValue];
    }
    return configuration;
}

+ (CLLocation *)locationForDictionary:(NSDictionary *)locationDict
{
    if (locationDict == nil) {
        return nil;
    }

    NSNumber *latitude = locationDict[@"latitude"];
    NSNumber *longitude = locationDict[@"longitude"];
    NSNumber *altitude = locationDict[@"altitude"];
    NSNumber *horizontalAccuracy = locationDict[@"accuracy"];
    NSNumber *verticalAccuracy = locationDict[@"verticalAccuracy"];
    NSNumber *course = locationDict[@"course"];
    NSNumber *speed = locationDict[@"speed"];
    NSNumber *timestamp = locationDict[@"timestamp"];

    NSDate *locationDate = timestamp != nil ? [NSDate dateWithTimeIntervalSince1970:timestamp.doubleValue] : [NSDate date];
    CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(latitude.doubleValue, longitude.doubleValue);
    CLLocation *location = [[CLLocation alloc] initWithCoordinate:coordinate
                                                         altitude:altitude.doubleValue
                                               horizontalAccuracy:horizontalAccuracy.doubleValue
                                                 verticalAccuracy:verticalAccuracy.doubleValue
                                                           course:course.doubleValue
                                                            speed:speed.doubleValue
                                                        timestamp:locationDate];

    return location;
}

+ (AMAAppMetricaPreloadInfo *)preloadInfoForDictionary:(NSDictionary *)preloadInfoDict
{
    if (preloadInfoDict == nil) {
        return nil;
    }

    NSString *trackingId = preloadInfoDict[@"trackingId"];
    AMAAppMetricaPreloadInfo *preloadInfo = [[AMAAppMetricaPreloadInfo alloc] initWithTrackingIdentifier:trackingId];

    NSDictionary *additionalInfo = preloadInfoDict[@"additionalInfo"];
    if (additionalInfo != nil) {
        for (NSString *key in additionalInfo) {
            [preloadInfo setAdditionalInfo:additionalInfo[key] forKey:key];
        }
    }

    return preloadInfo;
}

+ (nullable AMAECommerceScreen *) toEcommerceScreen:(nullable NSDictionary *)screenInfo
{
    if (screenInfo == nil) {
        return nil;
    }

    NSString * screenName = screenInfo[@"name"];
    if (screenName == nil) {
        return nil;
    }

    AMAECommerceScreen *screen = [[AMAECommerceScreen alloc] initWithName:screenName
                                                       categoryComponents:screenInfo[@"categoriesPath"]
                                                              searchQuery:screenInfo[@"searchQuery"]
                                                                  payload:screenInfo[@"payload"]
    ];
    
    return screen;
}

+ (nullable AMAECommerceReferrer *) toEcommerceReferer:(nullable NSDictionary *)refererInfo
{
    if (refererInfo == nil) {
        return nil;
    }

    NSString * type = refererInfo[@"type"];
    NSString * identifier = refererInfo[@"identifier"];
    if (type == nil && identifier == nil) {
        return nil;
    }

    AMAECommerceScreen *screen = [self toEcommerceScreen:refererInfo[@"screen"]];
    AMAECommerceReferrer *referrer = [[AMAECommerceReferrer alloc] initWithType:type
                                                                     identifier:identifier
                                                                         screen:screen
    ];
    
    return referrer;
}

+ (nullable AMAECommercePrice *) toEcommercePrice:(nullable NSDictionary *)priceInfo
{
    if (priceInfo == nil) {
        return nil;
    }

    NSString *amount = [priceInfo[@"amount"] stringValue];
    NSString *unit = priceInfo[@"unit"];
    if (amount == nil || unit == nil) {
        return nil;
    }

    AMAECommerceAmount *fiat = [[AMAECommerceAmount alloc] initWithUnit:unit
                                                                  value:[NSDecimalNumber decimalNumberWithString:amount]
    ];
    AMAECommercePrice *price = [[AMAECommercePrice alloc] initWithFiat:fiat];
    
    return price;
}

+ (nullable AMAECommerceProduct *) toEcommerceProduct:(nullable NSDictionary *)productInfo
{
    if (productInfo == nil) {
        return nil;
    }
    
    NSString * productId = productInfo[@"id"];
    if (productId == nil) {
        return nil;
    }

    AMAECommercePrice *actualPrice = [self toEcommercePrice:productInfo[@"actualPrice"]];
    AMAECommercePrice *originalPrice = [self toEcommercePrice:productInfo[@"originalPrice"]];
    AMAECommerceProduct *product = [[AMAECommerceProduct alloc] initWithSKU:productId
                                                                       name:productInfo[@"name"]
                                                         categoryComponents:productInfo[@"categoriesPath"]
                                                                    payload:productInfo[@"payload"]
                                                                actualPrice:actualPrice
                                                              originalPrice:originalPrice
                                                                 promoCodes:nil
    ];
    
    return product;
}

+ (nullable AMAECommerceCartItem *) toEcommerceCartItem:(nullable NSDictionary *)cartItemInfo :(nullable NSDictionary *)referrerInfo
{
    if (cartItemInfo == nil) {
        return nil;
    }

    AMAECommerceProduct *product = [self toEcommerceProduct:cartItemInfo[@"product"]];
    AMAECommerceReferrer *referrer = [self toEcommerceReferer:referrerInfo];
    NSDecimalNumber *quantity = [NSDecimalNumber decimalNumberWithString:[cartItemInfo[@"quantity"] stringValue]];
    AMAECommerceCartItem *cartItem = [[AMAECommerceCartItem alloc] initWithProduct:product
                                                                          quantity:quantity
                                                                           revenue:product.actualPrice
                                                                          referrer:referrer
    ];
    
    return cartItem;
}

+ (nullable AMAECommerceOrder *) toEcommerceOrder:(nullable NSDictionary *)orderInfo
{
    if (orderInfo == nil) {
        return nil;
    }
    
    
    NSString * identifier = orderInfo[@"identifier"];
    if (identifier == nil) {
        return nil;
    }

    
    NSMutableArray<AMAECommerceCartItem *> *cartItems = [[NSMutableArray alloc] init];
    [orderInfo[@"cartItems"] enumerateObjectsUsingBlock:^(id cartItemInfo, NSUInteger idx, BOOL * _Nonnull stop) {
        AMAECommerceCartItem *cartItem = [self toEcommerceCartItem:cartItemInfo :nil];
        if (cartItem != nil) {
            [cartItems addObject:cartItem];
        }
    }];
    if (cartItems.count == 0) {
        return nil;
    }

    AMAECommerceOrder *order = [[AMAECommerceOrder alloc] initWithIdentifier:identifier
                                                                   cartItems:cartItems
                                                                     payload:orderInfo[@"payload"]
    ];
    
    return order;
}

+ (NSString *)stringFromRequestDeviceIDError:(NSError *)error
{
    if (error == nil) {
        return nil;
    }
    if ([error.domain isEqualToString:NSURLErrorDomain]) {
        return @"NETWORK";
    }
    return @"UNKNOWN";
}

@end
