//
//  MFSizeObject.m
//  mobilefirst
//
//  Created by Scott Pfeil on 12/20/16.
//  Copyright © 2016 Verizon Wireless. All rights reserved.
//

#import <MVMCoreUI/MFSizeObject.h>
#import "MVMCoreUISplitViewController.h"
@import MVMCore.MVMCoreGetterUtility;

CGFloat const MFSizeiPhone4HeightThreshold = 490;
CGFloat const MFSizeiPhone5HeightThreshold = 578;

CGFloat const MFSizeSmalliPhoneThreshold = 330;
CGFloat const MFSizeLargeiPhoneThreshold = 400;
CGFloat const MFSizeStandardiPadPortraitThreshold = 600;
CGFloat const MFSizeStandardiPadLandscapeThreshold = 1000;
CGFloat const MFSizeiPadProLandscapeThreshold = 1300;
CGFloat const MFSizeMostlySweetSpotThreshold = 750;


@interface MFSizeObject ()

@property (nonatomic) BOOL maximumSizeSet;
@property (strong, nonatomic) NSMutableArray <MFSizeThreshold *>*customThresholds;

@end

@implementation MFSizeObject

+ (CGFloat)getScaledValue:(CGFloat)value forSize:(CGFloat)size fromBase:(nullable NSNumber *)base {
    CGFloat baseFloat = 375.0;
    if (base != nil) {
        baseFloat = [base floatValue];
    }
    return value * (size/baseFloat);
}

- (void)setMaximumSize:(CGFloat)maximumSize {
    self.maximumSizeSet = YES;
    _maximumSize = maximumSize;
}

- (instancetype)init {
    if (self = [super init]) {
    }
    return self;
}

#pragma mark - Size Initializers

+ (instancetype)sizeObjectWithStandardSize:(CGFloat)standardSize {
    MFSizeObject *object = [[MFSizeObject alloc] init];
    object.standardSize = standardSize;
    return object;
}

+ (nullable instancetype)sizeObjectWithScalingStandardSize:(CGFloat)standardSize {
    MFSizeObject *object = [[MFSizeObject alloc] init];
    object.standardSize = standardSize;
    object.scaleStandardSize = YES;
    return object;
}

+ (instancetype)sizeObjectWithStandardSize:(CGFloat)standardSize smalliPhoneSize:(CGFloat)smalliPhoneSize standardiPadPortraitSize:(CGFloat)standardiPadPortraitSize {
    MFSizeObject *object = [MFSizeObject sizeObjectWithStandardSize:standardSize smalliPhoneSize:smalliPhoneSize];
    [object addSizeForStandardiPadPortaitThreshold:standardiPadPortraitSize];
    return object;
}

+ (instancetype)sizeObjectWithStandardSize:(CGFloat)standardSize standardiPadPortraitSize:(CGFloat)standardiPadPortraitSize {
    MFSizeObject *object = [MFSizeObject sizeObjectWithStandardSize:standardSize];
    [object addSizeForStandardiPadPortaitThreshold:standardiPadPortraitSize];
    return object;
}

+ (instancetype)sizeObjectWithStandardSize:(CGFloat)standardSize smalliPhoneSize:(CGFloat)smalliPhoneSize {
    MFSizeObject *object = [MFSizeObject sizeObjectWithStandardSize:standardSize];
    [object addSizeForSmalliPhoneThreshold:smalliPhoneSize];
    return object;
}

+ (instancetype)sizeObjectWithStandardSize:(CGFloat)standardSize standardiPadPortraitSize:(CGFloat)standardiPadPortraitSize iPadProLandscapeSize:(CGFloat)iPadProLandscapeSize {
    MFSizeObject *object = [MFSizeObject sizeObjectWithStandardSize:standardSize standardiPadPortraitSize:standardiPadPortraitSize];
    [object addLargerThanCustomSize:iPadProLandscapeSize forThreshold:MFSizeiPadProLandscapeThreshold];
    return object;
}

+ (nullable instancetype)sizeObjectWithStandardSize:(CGFloat)standardSize smalliPhoneSize:(CGFloat)smalliPhoneSize standardiPadPortraitSize:(CGFloat)standardiPadPortraitSize iPadProLandscapeSize:(CGFloat)iPadProLandscapeSize {
    MFSizeObject *object = [MFSizeObject sizeObjectWithStandardSize:standardSize smalliPhoneSize:smalliPhoneSize standardiPadPortraitSize:standardiPadPortraitSize];
    [object addLargerThanCustomSize:iPadProLandscapeSize forThreshold:MFSizeiPadProLandscapeThreshold];
    return object;
}

#pragma mark - Block Initializers

+ (nullable instancetype)sizeObjectWithStandardSizeBlock:(nonnull void (^)(void))block {
    MFSizeObject *object = [[MFSizeObject alloc] init];
    object.standardThresholdBlock = block;
    return object;
}

+ (nullable instancetype)sizeObjectWithStandardBlock:(nonnull void (^)(void))standardBlock smalliPhoneBlock:(nonnull void (^)(void))smalliPhoneBlock standardiPadPortraitBlock:(nonnull void (^)(void))standardiPadPortraitBlock {
    MFSizeObject *object = [MFSizeObject sizeObjectWithStandardBlock:standardBlock smalliPhoneBlock:smalliPhoneBlock];
    [object addBlockForStandardiPadPortaitThreshold:standardiPadPortraitBlock];
    return object;
}

+ (nullable instancetype)sizeObjectWithStandardBlock:(nonnull void (^)(void))standardBlock standardiPadPortraitBlock:(nonnull void (^)(void))standardiPadPortraitBlock {
    MFSizeObject *object = [MFSizeObject sizeObjectWithStandardSizeBlock:standardBlock];
    [object addBlockForStandardiPadPortaitThreshold:standardiPadPortraitBlock];
    return object;
}

+ (nullable instancetype)sizeObjectWithStandardBlock:(nonnull void (^)(void))standardBlock smalliPhoneBlock:(nonnull void (^)(void))smalliPhoneBlock {
    MFSizeObject *object = [MFSizeObject sizeObjectWithStandardSizeBlock:standardBlock];
    [object addBlockForSmalliPhoneThreshold:smalliPhoneBlock];
    return object;
}

+ (nullable instancetype)sizeObjectWithStandardBlock:(nonnull void (^)(void))standardBlock standardiPadPortraitBlock:(nonnull void (^)(void))standardiPadPortraitBlock iPadProLandscapeBlock:(nonnull void (^)(void))iPadProLandscapeBlock {
    MFSizeObject *object = [MFSizeObject sizeObjectWithStandardBlock:standardBlock standardiPadPortraitBlock:standardiPadPortraitBlock];
    [object addLargerThanCustomThreshold:MFSizeiPadProLandscapeThreshold block:iPadProLandscapeBlock];
    return object;
}

+ (nullable instancetype)sizeObjectWithStandardBlock:(nonnull void (^)(void))standardBlock smalliPhoneBlock:(nonnull void (^)(void))smalliPhoneBlock standardiPadPortraitBlock:(nonnull void (^)(void))standardiPadPortraitBlock iPadProLandscapeBlock:(nonnull void (^)(void))iPadProLandscapeBlock {
    MFSizeObject *object = [MFSizeObject sizeObjectWithStandardBlock:standardBlock smalliPhoneBlock:smalliPhoneBlock standardiPadPortraitBlock:standardiPadPortraitBlock];
    [object addLargerThanCustomThreshold:MFSizeiPadProLandscapeThreshold block:iPadProLandscapeBlock];
    return object;
}

#pragma mark - Size Getters

- (CGFloat)getValueBasedOnDetailWidth {
    return [self getValueBasedOnSize:[MVMCoreUISplitViewController getDetailViewWidth]];
}

- (CGFloat)getValueBasedOnApplicationWidth {
    return [self getValueBasedOnSize:[MVMCoreUISplitViewController getApplicationViewWidth]];
}

- (CGFloat)getValueBasedOnScreenSize {
    CGRect screenFrame = [[UIScreen mainScreen] bounds];
    if ([MVMCoreGetterUtility isOnIPad]) {
        if (UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation)) {
            return [self getValueBasedOnSize:CGRectGetWidth(screenFrame)];
        } else {
            return [self getValueBasedOnSize:CGRectGetHeight(screenFrame)];
        }
    } else {
        return [self getValueBasedOnSize:CGRectGetWidth(screenFrame)];
    }
}

- (CGFloat)getValueBasedOnScreenHeight {
    return [self getValueBasedOnSize:CGRectGetHeight([[UIScreen mainScreen] bounds])];
}

- (CGFloat)getValueBasedOnSize:(CGFloat)size {

    __block BOOL valueSet = NO;
    __block CGFloat value = 0;
    [self.customThresholds enumerateObjectsUsingBlock:^(MFSizeThreshold * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        if (obj.direction == MFSizeGreaterThan) {
            if (size > obj.threshold) {
                value = [obj getValueForSizeScalingIfNeeded:size];
                valueSet = YES;
                *stop = YES;
            }
        } else {
            if (size < obj.threshold) {
                value = [obj getValueForSizeScalingIfNeeded:size];
                valueSet = YES;
                *stop = YES;
            }
        }
    }];
    
    if (!valueSet) {
        value = self.standardSize;
        if (self.scaleStandardSize) {
            value = [MFSizeObject getScaledValue:value forSize:size fromBase:self.scaleStandardSizeBaseValue];
        }
    }
    
    if (self.maximumSizeSet && value > self.maximumSize) {
        value = self.maximumSize;
    }
    
    return value;
}

#pragma mark - Block performers

- (void)performBlockBaseOnScreenSize {
    CGRect screenFrame = [[UIScreen mainScreen] bounds];
    if ([MVMCoreGetterUtility isOnIPad]) {
        if (UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation)) {
            [self performBlockBaseOnSize:CGRectGetWidth(screenFrame)];
        } else {
            [self performBlockBaseOnSize:CGRectGetHeight(screenFrame)];
        }
    } else {
        [self performBlockBaseOnSize:CGRectGetWidth(screenFrame)];
    }
}

- (void)performBlockBaseOnDetailWidth {
    [self performBlockBaseOnSize:[MVMCoreUISplitViewController getDetailViewWidth]];
}

- (void)performBlockBaseOnApplicationWidth {
    [self performBlockBaseOnSize:[MVMCoreUISplitViewController getApplicationViewWidth]];
}

- (void)performBlockBaseOnScreenHeight {
    [self performBlockBaseOnSize:CGRectGetHeight([[UIScreen mainScreen] bounds])];
}

- (void)performBlockBaseOnSize:(CGFloat)size {

    __block BOOL thresholdFound = NO;
    [self.customThresholds enumerateObjectsUsingBlock:^(MFSizeThreshold * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        if (obj.direction == MFSizeGreaterThan) {
            if (size > obj.threshold) {
                if (obj.thresholdBlock) {
                    obj.thresholdBlock();
                }
                thresholdFound = YES;
                *stop = YES;
            }
        } else {
            if (size < obj.threshold) {
                if (obj.thresholdBlock) {
                    obj.thresholdBlock();
                }
                thresholdFound = YES;
                *stop = YES;
            }
        }
    }];
    
    if (!thresholdFound && self.standardThresholdBlock) {
        self.standardThresholdBlock();
    }
}

#pragma mark - Add size thresholds

- (void)addCustomSize:(MFSizeThreshold *)sizeThreshold {
    
    if (sizeThreshold) {
        if (!self.customThresholds) {
            self.customThresholds = [NSMutableArray array];
        }
        [self.customThresholds addObject:sizeThreshold];
        
        [self.customThresholds sortUsingComparator:^NSComparisonResult(MFSizeThreshold   * _Nonnull obj1, MFSizeThreshold   * _Nonnull obj2) {
            if (obj1.direction != obj2.direction) {
                if (obj1.direction == MFSizeGreaterThan) {
                    return NSOrderedAscending;
                } else {
                    return NSOrderedDescending;
                }
            } else if (obj1.direction == MFSizeGreaterThan) {
                if (obj1.threshold > obj2.threshold) {
                    return NSOrderedAscending;
                } else {
                    return NSOrderedDescending;
                }
            } else {
                if (obj1.threshold < obj2.threshold) {
                    return NSOrderedAscending;
                } else {
                    return NSOrderedDescending;
                }
            }
        }];
    }
}

- (void)addCustomSize:(CGFloat)size forThreshold:(CGFloat)threshold compareDirection:(MFSizeCompareDirection)compareDirection {

    MFSizeThreshold *sizeThreshold = [[MFSizeThreshold alloc] initWithSize:size forThreshold:threshold compareDirection:compareDirection];
    [self addCustomSize:sizeThreshold];
}

- (void)addLargerThanCustomSize:(CGFloat)size forThreshold:(CGFloat)threshold {
    MFSizeThreshold *sizeThreshold = [MFSizeThreshold largerThanCustomSize:size forThreshold:threshold];
    [self addCustomSize:sizeThreshold];
}

- (void)addSmallerThanCustomSize:(CGFloat)size forThreshold:(CGFloat)threshold {
    MFSizeThreshold *sizeThreshold = [MFSizeThreshold smallerThanCustomSize:size forThreshold:threshold];
    [self addCustomSize:sizeThreshold];
}

- (void)addScalingLargerThanCustomSize:(CGFloat)size forThreshold:(CGFloat)threshold {
    MFSizeThreshold *sizeThreshold = [MFSizeThreshold scalingLargerThanCustomSize:size forThreshold:threshold];
    [self addCustomSize:sizeThreshold];
}

- (void)addScalingSmallerThanCustomSize:(CGFloat)size forThreshold:(CGFloat)threshold {
    MFSizeThreshold *sizeThreshold = [MFSizeThreshold scalingSmallerThanCustomSize:size forThreshold:threshold];
    [self addCustomSize:sizeThreshold];
}

- (void)addSizeForSmalliPhoneThreshold:(CGFloat)size {
    [self addSmallerThanCustomSize:size forThreshold:MFSizeSmalliPhoneThreshold];
}

- (void)addSizeForStandardiPadPortaitThreshold:(CGFloat)size {
    [self addLargerThanCustomSize:size forThreshold:MFSizeStandardiPadPortraitThreshold];
}

- (void)addSizeForiPadProLandscapeThreshold:(CGFloat)size {
    [self addLargerThanCustomSize:size forThreshold:MFSizeiPadProLandscapeThreshold];
}

#pragma mark - Add block thresholds

- (void)addCustomThreshold:(CGFloat)threshold compareDirection:(MFSizeCompareDirection)compareDirection block:(nonnull void (^)(void))block {
    MFSizeThreshold *sizeThreshold = [[MFSizeThreshold alloc] initWithThreshold:threshold compareDirection:compareDirection block:block];
    [self addCustomSize:sizeThreshold];
}

- (void)addLargerThanCustomThreshold:(CGFloat)threshold block:(nonnull void (^)(void))block {
    MFSizeThreshold *sizeThreshold = [MFSizeThreshold largerThanCustomThreshold:threshold block:block];
    [self addCustomSize:sizeThreshold];
}

- (void)addSmallerThanCustomThreshold:(CGFloat)threshold block:(nonnull void (^)(void))block {
    MFSizeThreshold *sizeThreshold = [MFSizeThreshold smallerThanCustomThreshold:threshold block:block];
    [self addCustomSize:sizeThreshold];
}

- (void)addScalingLargerThanCustomThreshold:(CGFloat)threshold block:(nonnull void (^)(void))block {
    MFSizeThreshold *sizeThreshold = [MFSizeThreshold scalingLargerThanCustomThreshold:threshold block:block];
    [self addCustomSize:sizeThreshold];
}

- (void)addScalingSmallerThanCustomThreshold:(CGFloat)threshold block:(nonnull void (^)(void))block {
    MFSizeThreshold *sizeThreshold = [MFSizeThreshold scalingSmallerThanCustomThreshold:threshold block:block];
    [self addCustomSize:sizeThreshold];
}

- (void)addBlockForSmalliPhoneThreshold:(nonnull void (^)(void))block {
    [self addSmallerThanCustomThreshold:MFSizeSmalliPhoneThreshold block:block];
}

- (void)addBlockForStandardiPadPortaitThreshold:(nonnull void (^)(void))block {
    [self addLargerThanCustomThreshold:MFSizeStandardiPadPortraitThreshold block:block];
}

- (void)addBlockForiPadProLandscapeThreshold:(nonnull void (^)(void))block {
    [self addLargerThanCustomThreshold:MFSizeiPadProLandscapeThreshold block:block];

}

@end
