//
//  NSLayoutConstraint+MFConvenience.m
//  myverizon
//
//  Created by Chris Yang on 1/15/16.
//  Copyright © 2016 Verizon Wireless. All rights reserved.
//

#import "NSLayoutConstraint+MFConvenience.h"

//constraint constants
NSString *const ConstraintTop = @"top";
NSString *const ConstraintBot = @"bot";
NSString *const ConstraintLeading = @"leading";
NSString *const ConstraintTrailing = @"trailing";
NSString *const ConstraintCenterX = @"centerX";
NSString *const ConstraintCenterY = @"centerY";
NSString *const ConstraintHeight = @"height";
NSString *const ConstraintWidth = @"width";

@implementation NSLayoutConstraint (MFConvenience)

+ (NSDictionary *)constraintPinSubviewToSuperview:(UIView *)subview {
    return [NSLayoutConstraint constraintPinSubview:subview pinTop:YES pinBottom:YES pinLeft:YES pinRight:YES];
}

+ (nullable NSDictionary *)constraintPinTopSubview:(nonnull UIView *)subview topConstant:(CGFloat)topConstant {
    return [NSLayoutConstraint constraintPinSubview:subview pinTop:true topConstant:topConstant pinBottom:false bottomConstant:0 pinLeft:false leftConstant:0 pinRight:false rightConstant:0];
}

+ (nullable NSDictionary *)constraintPinBottomSubview:(nonnull UIView *)subview bottomConstant:(CGFloat)bottomConstant {
    return [NSLayoutConstraint constraintPinSubview:subview pinTop:false topConstant:0 pinBottom:true bottomConstant:bottomConstant pinLeft:false leftConstant:0 pinRight:false rightConstant:0];
}

+ (nullable NSDictionary *)constraintPinLeftSubview:(nonnull UIView *)subview leftConstant:(CGFloat)leftConstant {
    return [NSLayoutConstraint constraintPinSubview:subview pinTop:false topConstant:0 pinBottom:false bottomConstant:0 pinLeft:true leftConstant:leftConstant pinRight:false rightConstant:0];
}

+ (nullable NSDictionary *)constraintPinRightSubview:(nonnull UIView *)subview rightConstant:(CGFloat)rightConstant {
    return [NSLayoutConstraint constraintPinSubview:subview pinTop:false topConstant:0 pinBottom:false bottomConstant:0 pinLeft:false leftConstant:0 pinRight:true rightConstant:rightConstant];
}

+ (NSDictionary *)constraintPinSubview:(UIView *)subview pinTop:(BOOL)pinTop pinBottom:(BOOL)pinBottom pinLeft:(BOOL)pinLeft pinRight:(BOOL)pinRight {
    return [NSLayoutConstraint constraintPinSubview:subview pinTop:pinTop topConstant:0 pinBottom:pinBottom bottomConstant:0 pinLeft:pinLeft leftConstant:0 pinRight:pinRight rightConstant:0];
}

+ (nullable NSDictionary *)constraintPinSubview:(nullable UIView *)subview topRelation:(NSLayoutRelation)topRelation bottomRelation:(NSLayoutRelation)bottomRelation leftRelation:(NSLayoutRelation)leftRelation rightRelation:(NSLayoutRelation)rightRelation {
    return [self constraintPinSubview:subview pinTop:YES topConstant:0 topRelation:topRelation pinBottom:YES bottomConstant:0 bottomRelation:bottomRelation pinLeft:YES leftConstant:0 leftRelation:leftRelation pinRight:YES rightConstant:0 rightRelation:rightRelation];
}

+ (NSDictionary *)constraintPinSubview:(UIView *)subview pinTop:(BOOL)pinTop topConstant:(CGFloat)topConstant pinBottom:(BOOL)pinBottom bottomConstant:(CGFloat)bottomConstant pinLeft:(BOOL)pinLeft leftConstant:(CGFloat)leftConstant pinRight:(BOOL)pinRight rightConstant:(CGFloat)rightConstant {
    return [self constraintPinSubview:subview pinTop:pinTop topConstant:topConstant topRelation:NSLayoutRelationEqual pinBottom:pinBottom bottomConstant:bottomConstant bottomRelation:NSLayoutRelationEqual pinLeft:pinLeft leftConstant:leftConstant leftRelation:NSLayoutRelationEqual pinRight:pinRight rightConstant:rightConstant rightRelation:NSLayoutRelationEqual];
}

+ (NSDictionary *)constraintPinSubview:(UIView *)subview pinTop:(BOOL)pinTop topConstant:(CGFloat)topConstant topRelation:(NSLayoutRelation)topRelation pinBottom:(BOOL)pinBottom bottomConstant:(CGFloat)bottomConstant bottomRelation:(NSLayoutRelation)bottomRelation pinLeft:(BOOL)pinLeft leftConstant:(CGFloat)leftConstant leftRelation:(NSLayoutRelation)leftRelation pinRight:(BOOL)pinRight rightConstant:(CGFloat)rightConstant rightRelation:(NSLayoutRelation)rightRelation {
    UIView *superview = subview.superview;
    NSMutableDictionary *constraintDic = [[NSMutableDictionary alloc] init];
    if (pinTop) {
        NSLayoutConstraint *top = [NSLayoutConstraint constraintWithItem:subview attribute:NSLayoutAttributeTop relatedBy:topRelation toItem:superview attribute:NSLayoutAttributeTop multiplier:1 constant:topConstant];
        top.priority = 999;
        top.active = YES;
        [constraintDic setObject:top forKey:ConstraintTop];
    }
    if (pinBottom) {
        NSLayoutConstraint *bottom = [NSLayoutConstraint constraintWithItem:superview attribute:NSLayoutAttributeBottom relatedBy:bottomRelation toItem:subview attribute:NSLayoutAttributeBottom multiplier:1 constant:bottomConstant];
        bottom.priority = 999;
        bottom.active = YES;
        [constraintDic setObject:bottom forKey:ConstraintBot];
    }
    if (pinLeft) {
        NSLayoutConstraint *leading = [NSLayoutConstraint constraintWithItem:subview attribute:NSLayoutAttributeLeading relatedBy:leftRelation toItem:superview attribute:NSLayoutAttributeLeading multiplier:1 constant:leftConstant];
        leading.priority = 999;
        leading.active = YES;
        [constraintDic setObject:leading forKey:ConstraintLeading];
    }
    if (pinRight) {
        NSLayoutConstraint *trailing = [NSLayoutConstraint constraintWithItem:superview attribute:NSLayoutAttributeTrailing relatedBy:rightRelation toItem:subview attribute:NSLayoutAttributeTrailing multiplier:1 constant:rightConstant];
        trailing.priority = 999;
        trailing.active = YES;
        [constraintDic setObject:trailing forKey:ConstraintTrailing];
    }
    return constraintDic;
}

+ (NSDictionary *)constraintPinSubviewToCenterOfSuperview:(UIView *)subview {
    return [NSLayoutConstraint constraintPinSubview:subview pinCenterX:YES pinCenterY:YES];
}

+ (NSDictionary *)constraintPinSubview:(UIView *)subview pinCenterX:(BOOL)pinCenterX pinCenterY:(BOOL)pinCenterY {
    return [NSLayoutConstraint constraintPinSubview:subview pinCenterX:pinCenterX centerXConstant:0 pinCenterY:pinCenterY centerYConstant:0];
}

+ (NSDictionary *)constraintPinSubview:(UIView *)subview pinCenterX:(BOOL)pinCenterX centerXConstant:(CGFloat)centerXConstant pinCenterY:(BOOL)pinCenterY centerYConstant:(CGFloat)centerYConstant {
    UIView *superview = subview.superview;
    NSMutableDictionary *constraintDic = [[NSMutableDictionary alloc]init];
    if (pinCenterX) {
        NSLayoutConstraint *centerX = [NSLayoutConstraint constraintWithItem:subview attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:superview attribute:NSLayoutAttributeCenterX multiplier:1 constant:centerXConstant];
        centerX.priority = 999;
        centerX.active = YES;
        [constraintDic setObject:centerX forKey:ConstraintCenterX];
    }
    if (pinCenterY) {
        NSLayoutConstraint *centerY = [NSLayoutConstraint constraintWithItem:subview attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:superview attribute:NSLayoutAttributeCenterY multiplier:1 constant:centerYConstant];
        centerY.priority = 999;
        centerY.active = YES;
        [constraintDic setObject:centerY forKey:ConstraintCenterY];
    }
    return constraintDic;
}

+ (nullable NSDictionary *)constraintPinView:(nonnull UIView *)view heightConstraint:(BOOL)pinHeight heightConstant:(CGFloat)heightConstant widthConstraint:(BOOL)pinWidth widthConstant:(CGFloat)widthConstant {
     NSMutableDictionary *constraintDic = [[NSMutableDictionary alloc] init];
    if (pinHeight) {
        NSLayoutConstraint *height = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:heightConstant];
        height.priority = 999;
        height.active = YES;
        [constraintDic setObject:height forKey:ConstraintHeight];
    }
    if (pinWidth) {
        NSLayoutConstraint *width = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:widthConstant];
        width.priority = 999;
        width.active = YES;
        [constraintDic setObject:width forKey:ConstraintWidth];
    }
    return constraintDic;
}

+ (NSLayoutConstraint *)constraintPinFirstView:(nonnull UIView *)firstView toSecondView:(nonnull UIView *)secondView withConstant:(CGFloat)constant directionVertical:(BOOL)directionVertical {
    //@Chris: Added the commont braces as to avoid crash when a negative constant comes in -Arun
    NSString *pinString;
    if (directionVertical) {
        pinString = [NSString stringWithFormat:@"V:[firstView]-(%f)-[secondView]",constant];
    } else {
        pinString = [NSString stringWithFormat:@"H:[firstView]-(%f)-[secondView]",constant];
    }
   
    NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:pinString options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(firstView, secondView)];
    
    NSLayoutConstraint *constraint = constraints[0];
    constraint.priority = 999;
    [NSLayoutConstraint activateConstraints:constraints];
    return constraint;
}

+ (nullable NSDictionary *)constraintAlignView:(nonnull UIView *)firstView toSecondView:(nonnull UIView *)secondView alignX:(BOOL)alignX alignY:(BOOL)alignY {
    
    NSMutableDictionary *constraintsDictionary = [[NSMutableDictionary alloc] init];
    if (alignX) {
        NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:firstView attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:secondView attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0.0];
        [firstView.superview addConstraint:constraint];
        [constraintsDictionary setObject:constraint forKey:ConstraintCenterX];
    }
    if (alignY) {
        NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:firstView attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:secondView attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0.0];
        [firstView.superview addConstraint:constraint];
        [constraintsDictionary setObject:constraint forKey:ConstraintCenterY];
    }
    return constraintsDictionary;
}

#pragma mark - With Margins

+ (nonnull NSDictionary *)pinViewToSuperview:(nonnull UIView *)subview useMargins:(BOOL)useMargins {
    return [NSLayoutConstraint pinViewToSuperview:subview useMargins:useMargins pinTop:YES topConstant:0 pinBottom:YES bottomConstant:0 pinLeft:YES leftConstant:0 pinRight:YES rightConstant:0];
}

+ (nonnull NSDictionary *)pinViewToSuperview:(nonnull UIView *)subview useMargins:(BOOL)useMargins pinTop:(BOOL)pinTop pinBottom:(BOOL)pinBottom pinLeft:(BOOL)pinLeft pinRight:(BOOL)pinRight {
    return [NSLayoutConstraint pinViewToSuperview:subview useMargins:useMargins pinTop:pinTop topConstant:0 pinBottom:pinBottom bottomConstant:0 pinLeft:pinLeft leftConstant:0 pinRight:pinRight rightConstant:0];
}

+ (NSDictionary *)pinViewToSuperview:(UIView *)subview useMargins:(BOOL)useMargins pinTop:(BOOL)pinTop topConstant:(CGFloat)topConstant pinBottom:(BOOL)pinBottom bottomConstant:(CGFloat)bottomConstant pinLeft:(BOOL)pinLeft leftConstant:(CGFloat)leftConstant pinRight:(BOOL)pinRight rightConstant:(CGFloat)rightConstant {
    NSMutableDictionary *constraints = [[NSMutableDictionary alloc] init];
    if (pinTop) {
        [constraints setObject:[self pinViewTopToSuperview:subview useMargins:useMargins constant:topConstant] forKey:ConstraintTop];
    }
    if (pinLeft) {
        [constraints setObject:[self pinViewLeftToSuperview:subview useMargins:useMargins constant:topConstant] forKey:ConstraintLeading];
    }
    if (pinRight) {
        [constraints setObject:[self pinViewRightToSuperview:subview useMargins:useMargins constant:topConstant] forKey:ConstraintTrailing];
    }
    if (pinBottom) {
        [constraints setObject:[self pinViewBottomToSuperview:subview useMargins:useMargins constant:topConstant] forKey:ConstraintBot];
    }
    return constraints;
}

+ (NSLayoutConstraint *)pinViewTopToSuperview:(UIView *)view useMargins:(BOOL)useMargins constant:(CGFloat)constant {
    return [view.topAnchor constraintEqualToAnchor:(useMargins ? view.superview.layoutMarginsGuide.topAnchor : view.superview.topAnchor) constant:constant];
}

+ (NSLayoutConstraint *)pinViewLeftToSuperview:(UIView *)view useMargins:(BOOL)useMargins constant:(CGFloat)constant {
    return [view.leftAnchor constraintEqualToAnchor:(useMargins ? view.superview.layoutMarginsGuide.leftAnchor : view.superview.leftAnchor) constant:constant];
}

+ (NSLayoutConstraint *)pinViewRightToSuperview:(UIView *)view useMargins:(BOOL)useMargins constant:(CGFloat)constant {
    return [(useMargins ? view.superview.layoutMarginsGuide.rightAnchor : view.superview.rightAnchor) constraintEqualToAnchor:view.rightAnchor constant:constant];
}

+ (NSLayoutConstraint *)pinViewBottomToSuperview:(UIView *)view useMargins:(BOOL)useMargins constant:(CGFloat)constant {
    return [(useMargins ? view.superview.layoutMarginsGuide.bottomAnchor : view.superview.bottomAnchor) constraintEqualToAnchor:view.bottomAnchor constant:constant];
}

#pragma mark - Scaling constraints

+ (nullable NSDictionary *)scalingConstraintPinSubview:(nullable UIView *)subview pinTop:(BOOL)pinTop topConstant:(CGFloat)topConstant pinBottom:(BOOL)pinBottom bottomConstant:(CGFloat)bottomConstant pinLeft:(BOOL)pinLeft leftConstant:(CGFloat)leftConstant pinRight:(BOOL)pinRight rightConstant:(CGFloat)rightConstant baseConstant:(CGFloat)baseConstant {
    return [self scalingConstraintPinSubview:subview pinTop:pinTop topConstant:topConstant pinBottom:pinBottom bottomConstant:bottomConstant pinLeft:pinLeft leftConstant:leftConstant pinRight:pinRight rightConstant:rightConstant baseConstant:baseConstant anchor:nil];
}

+ (nullable NSDictionary *)scalingConstraintPinSubview:(nullable UIView *)subview pinTop:(BOOL)pinTop topConstant:(CGFloat)topConstant pinBottom:(BOOL)pinBottom bottomConstant:(CGFloat)bottomConstant pinLeft:(BOOL)pinLeft leftConstant:(CGFloat)leftConstant pinRight:(BOOL)pinRight rightConstant:(CGFloat)rightConstant baseConstant:(CGFloat)baseConstant anchor:(nullable NSLayoutDimension *)anchor {
    NSMutableDictionary *constraints = [[NSMutableDictionary alloc] init];
    if (pinTop){
        [constraints setObject:[self scalingPinViewTopToSuper:subview ratio:topConstant/baseConstant anchor:anchor] forKey:ConstraintTop];
    }
    if (pinBottom){
        [constraints setObject:[self scalingPinViewBottomToSuper:subview ratio:bottomConstant/baseConstant anchor:anchor] forKey:ConstraintBot];
    }
    if (pinLeft) {
        [constraints setObject:[self scalingPinViewLeftToSuper:subview ratio:leftConstant/baseConstant anchor:anchor] forKey:ConstraintLeading];
    }
    if (pinRight){
        [constraints setObject:[self scalingPinViewRightToSuper:subview ratio:rightConstant/baseConstant anchor:anchor] forKey:ConstraintTrailing];
    }
    return constraints;
}

+ (nonnull NSLayoutConstraint *)scalingPinViewLeftToSuper:(nonnull UIView *)view ratio:(CGFloat)ratio anchor:(nullable NSLayoutDimension *)anchor {
    NSLayoutConstraint *constraint = [self scalingConstraintPinView:view.superview toView:view layoutAxis:UILayoutConstraintAxisHorizontal relation:NSLayoutRelationEqual ratio:ratio anchor:anchor];
    constraint.active = YES;
    return constraint;
}

+ (nonnull NSLayoutConstraint *)scalingPinViewRightToSuper:(nonnull UIView *)view ratio:(CGFloat)ratio anchor:(nullable NSLayoutDimension *)anchor {
    NSLayoutConstraint *constraint = [self scalingConstraintPinView:view toView:view.superview layoutAxis:UILayoutConstraintAxisHorizontal relation:NSLayoutRelationEqual ratio:ratio anchor:anchor];
    constraint.active = YES;
    return constraint;
}

+ (nonnull NSLayoutConstraint *)scalingPinViewTopToSuper:(nonnull UIView *)view ratio:(CGFloat)ratio anchor:(nullable NSLayoutDimension *)anchor {
    NSLayoutConstraint *constraint = [self scalingConstraintPinView:view.superview toView:view layoutAxis:UILayoutConstraintAxisVertical relation:NSLayoutRelationEqual ratio:ratio anchor:anchor];
    constraint.active = YES;
    return constraint;
}

+ (nonnull NSLayoutConstraint *)scalingPinViewBottomToSuper:(nonnull UIView *)view ratio:(CGFloat)ratio anchor:(nullable NSLayoutDimension *)anchor {
    NSLayoutConstraint *constraint = [self scalingConstraintPinView:view toView:view.superview layoutAxis:UILayoutConstraintAxisVertical relation:NSLayoutRelationEqual ratio:ratio anchor:anchor];
    constraint.active = YES;
    return constraint;
}

+ (nonnull NSLayoutConstraint *)scalingConstraintPinView:(nonnull UIView *)view toView:(nonnull UIView *)toView layoutAxis:(UILayoutConstraintAxis)layoutAxis relation:(NSLayoutRelation)relation ratio:(CGFloat)ratio anchor:(nullable NSLayoutDimension *)anchor {
    
    NSLayoutDimension *dimension = nil;
    NSLayoutDimension *defaultAnchor = nil;
    if (layoutAxis == UILayoutConstraintAxisHorizontal) {
        if (view == toView.superview) {
            // Superview left edge to the subview left.
            dimension = [view.leftAnchor anchorWithOffsetToAnchor:toView.leftAnchor];
            defaultAnchor = view.widthAnchor;
        } else if (toView == view.superview) {
            // subview right edge to the superview right.
            dimension = [view.rightAnchor anchorWithOffsetToAnchor:toView.rightAnchor];
            defaultAnchor = toView.widthAnchor;
        } else {
            // view a to view b.
            dimension = [view.rightAnchor anchorWithOffsetToAnchor:toView.leftAnchor];
            defaultAnchor = view.superview.widthAnchor;
        }
    } else {
        if (view == toView.superview) {
            // Superview top edge to the subview top.
            dimension = [view.topAnchor anchorWithOffsetToAnchor:toView.topAnchor];
            defaultAnchor = view.widthAnchor;
        } else if (toView == view.superview) {
            // subview bottom edge to the superview bottom.
            dimension = [view.bottomAnchor anchorWithOffsetToAnchor:toView.bottomAnchor];
            defaultAnchor = toView.widthAnchor;
        } else {
            // view a to view b.
            dimension = [view.bottomAnchor anchorWithOffsetToAnchor:toView.topAnchor];
            defaultAnchor = view.superview.widthAnchor;
        }
    }
    
    // If no passed in anchor, use the default.
    if (!anchor) {
        anchor = defaultAnchor;
    }
    
    NSLayoutConstraint *constraint;
    switch (relation) {
        case NSLayoutRelationLessThanOrEqual:
            constraint = [dimension constraintLessThanOrEqualToAnchor:anchor multiplier:ratio];
            break;
        case NSLayoutRelationGreaterThanOrEqual:
            constraint = [dimension constraintGreaterThanOrEqualToAnchor:anchor multiplier:ratio];
            break;
        default:
            constraint = [dimension constraintEqualToAnchor:anchor multiplier:ratio];
            break;
    }
    return constraint;
}

@end
