//
//  KWMShoppingCart.m
//  iCemarose
//
//  Created by lee on 2017/5/18.
//  Copyright © 2017年 kollway. All rights reserved.
//

#import "KWMShoppingCart.h"
#import "KWMCartResult.h"
#import "KWMShopCartData.h"
#import <RegexKitLite/RegexKitLite.h>
#import <RXCollections/RXCollection.h>

@interface KWMShoppingCart ()

@property (nonatomic, strong) KWMCartResult *result;
//@property (nonatomic, assign) CGFloat version;
@property (nonatomic, strong) NSMutableArray<NSURLSessionDataTask *> *tasks;

@end

@implementation KWMShoppingCart

- (NSMutableArray<KWMShopCartModel *> *)items {
    return (NSMutableArray *)_result.items;
}

- (NSNumber *)count {
    return _result.item_count;
}

- (void)setResult:(KWMCartResult *)result {
    _result = result;
    [[KWMShopCartData alloc] syncCartProducts:result.items];
}

- (void)setResultNoSync:(KWMCartResult *)result {
    _result = result;
}

+ (instancetype)sharedInstance {
    static KWMShoppingCart *instance;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken,^{
        instance = [[super allocWithZone:NULL] init];
        instance.tasks = [[NSMutableArray alloc] init];
    });
    if (!instance.result) {
        [instance setResultNoSync:[KWMCartResult new]];
        instance.result.items = [[[KWMShopCartData alloc] getALLItems] mutableCopy];
        NSInteger count = 0;
        for (KWMShopCartModel *item in instance.items) {
            count += item.quantity;
        }
        instance.result.item_count = @(count);
    }
    return instance;
}

- (void) missionCompleted {
    [self.tasks removeObjectAtIndex:0];
    [self.tasks.firstObject resume];
}

- (void) addTasksObject:(NSURLSessionDataTask *)object {
    if (self.tasks.lastObject && [self.tasks.lastObject.currentRequest.URL.absoluteString isEqualToString:object.currentRequest.URL.absoluteString] && [object.currentRequest.URL.absoluteString isMatchedByRegex:@"cart.js$"]) {
        if(!self.sync) {
            return;
        }
    }
    [self.tasks addObject:object];
    if (self.tasks.count == 1) {
        [object resume];
    }
    
}

- (void)allItemsWithCallback:(ShoppingCartCallBack)callback {
//    CGFloat version = [[NSDate date] timeIntervalSince1970];
//    _version = version;
    __weak typeof(self) this = self;
    id task = [[KWMAPIManager sharedManager] getCartSuccess:^(NSURLSessionDataTask *task, KWMCartResult *result) {
        [this missionCompleted];
//        if (version == this.version) {
            [[KWMShoppingCart sharedInstance] setResult:result];
            callback(nil,result);
//        }
    } failure:^(NSURLSessionDataTask *task, NSError *error) {
        [this missionCompleted];
        callback(error,nil);
    }];
    [self addTasksObject:task];
}

- (void)increaseProductWithVariantId:(NSNumber *)variantId quantity:(NSInteger)quantity callback:(ShoppingCartCallBack)callback {
//    CGFloat version = [[NSDate date] timeIntervalSince1970];
//    _version = version;
    __weak typeof(self) this = self;
    id task = [[KWMAPIManager sharedManager] addProductWithVariantId:variantId quantity:quantity success:^(NSURLSessionDataTask *task, KWMRequestResult *result) {
        [this missionCompleted];
//        if (version == this.version) {
            [[KWMShoppingCart sharedInstance] allItemsWithCallback:^(NSError *error, KWMCartResult *cart) {
                if(this.sync)callback(error,cart);
            }];
//        }
    } failure:^(NSURLSessionDataTask *task, NSError *error) {
        [this missionCompleted];
//        callback(error,nil);
    }];
    [self addTasksObject:task];
    if(!this.sync)callback(nil,[self changeLocalCartWithVariantId:variantId quantity:quantity flag:1]);
}

- (void)changeProductWithVariantId:(NSNumber *)variantId quantity:(NSInteger)quantity callback:(ShoppingCartCallBack)callback {
//    CGFloat version = [[NSDate date] timeIntervalSince1970];
//    _version = version;
    __weak typeof(self) this = self;
    id task = [[KWMAPIManager sharedManager] changeProductWithVariantId:variantId quantity:quantity success:^(NSURLSessionDataTask *task, KWMCartResult *result) {
        [this missionCompleted];
//        if (version == this.version) {
            [[KWMShoppingCart sharedInstance] setResult:result];
        if(this.sync)callback(nil,result);
//        }
    } failure:^(NSURLSessionDataTask *task, NSError *error) {
        [this missionCompleted];
//        callback(error,nil);
    }];
    [self addTasksObject:task];
    if(!this.sync)callback(nil,[self changeLocalCartWithVariantId:variantId quantity:quantity flag:quantity ? 2 : 0]);
}

-(void)updateProductWithVariantIds:(NSArray<NSNumber *> *)variantIds quantitties:(NSArray<NSNumber *> *)quantites callback:(ShoppingCartCallBack)callback {
//    CGFloat version = [[NSDate date] timeIntervalSince1970];
//    _version = version;
    __weak typeof(self) this = self;
    id task = [[KWMAPIManager sharedManager] updateProductWithVariantIds:variantIds quantities:quantites success:^(NSURLSessionDataTask *task, KWMCartResult *result) {
        [this missionCompleted];
//        if (version == this.version) {
            [[KWMShoppingCart sharedInstance] setResult:result];
        if(this.sync)callback(nil,result);
//        }
    } failure:^(NSURLSessionDataTask *task, NSError *error) {
        [this missionCompleted];
//        callback(error,nil);
    }];
    [self addTasksObject:task];
    if(!this.sync) {
        for (int i=0; i<quantites.count && self.items.count; i++) {
            [self changeLocalCartWithVariantId:variantIds[i] quantity:quantites[i].integerValue flag:quantites[i].integerValue ? 2 : 0];
        }
        callback(nil,self.result);
    }
}

- (void)deleteProductWithVariantId:(NSNumber *)variantId callback:(ShoppingCartCallBack)callback {
    [self changeProductWithVariantId:variantId quantity:0 callback:callback];
}

- (void)clearCartWithCallback:(ShoppingCartCallBack)callback {
    NSMutableArray *quantity = [NSMutableArray new];
    NSArray *ids = [self.items rx_mapWithBlock:^id(KWMShopCartModel* each) {
        [quantity addObject:@(0)];
        return each.identifier;
    }];
    [self setResult:[KWMCartResult new]];
    __weak typeof(self) this = self;
    id task = [[KWMAPIManager sharedManager] updateProductWithVariantIds:ids quantities:quantity success:^(NSURLSessionDataTask *task, KWMCartResult *result) {
        [this missionCompleted];
        //        if (version == this.version) {
        [[KWMShoppingCart sharedInstance] setResult:result];
        callback(nil,result);
        //        }
    } failure:^(NSURLSessionDataTask *task, NSError *error) {
        [this missionCompleted];
        callback(error,nil);
    }];
    [self addTasksObject:task];
}

- (KWMCartResult *) changeLocalCartWithVariantId:(NSNumber *) variantId quantity:(NSInteger) quantity flag:(NSInteger) flag {
    NSMutableArray<KWMShopCartModel *> *items= self.items;
    NSInteger count = self.result.item_count.integerValue;
    BOOL processed = NO;
    NSUInteger size = items.count;
    for (int i=0;i < size; i++) {
        KWMShopCartModel *item = items[i];
        if (item.identifier.integerValue == variantId.integerValue) {
            switch (flag) {
                case 0:
                    count -= item.quantity;
                    [self.items removeObjectAtIndex:i];
                    break;
                case 1:
                    count += quantity;
                    item.quantity += quantity;
                    break;
                default:
                    count -= item.quantity - quantity;
                    item.quantity = quantity;
            }
            processed = YES;
            break;
        }
    }
    if (!processed) {
        KWMShopCartModel *model = [[KWMShopCartModel alloc] init];
        model.identifier = variantId.stringValue;
        model.quantity = quantity;
        count += quantity;
//        [items addObject:model];
        [items insertObject:model atIndex:0];
    }
    self.result.item_count = @(count);
    return self.result;
}

+ (id)allocWithZone:(struct _NSZone *)zone {
    return [KWMShoppingCart sharedInstance];
}

- (id)copy {
    return self;
}

- (id)mutableCopy {
    return self;
}

@end