//
//  YSMASConstraint.h
//  Masonry
//
//  Created by Jonas Budelmann on 22/07/13.
//  Copyright (c) 2013 cloudling. All rights reserved.
//

#import "YSMASUtilities.h"

/**
 *	Enables Constraints to be created with chainable syntax
 *  Constraint can represent single NSLayoutConstraint (YSMASViewConstraint) 
 *  or a group of NSLayoutConstraints (YSMASComposisteConstraint)
 */
@interface YSMASConstraint : NSObject

// Chaining Support

/**
 *	Modifies the NSLayoutConstraint constant,
 *  only affects YSMASConstraints in which the first item's NSLayoutAttribute is one of the following
 *  NSLayoutAttributeTop, NSLayoutAttributeLeft, NSLayoutAttributeBottom, NSLayoutAttributeRight
 */
- (YSMASConstraint * (^)(YSMASEdgeInsets insets))insets;

/**
 *	Modifies the NSLayoutConstraint constant,
 *  only affects YSMASConstraints in which the first item's NSLayoutAttribute is one of the following
 *  NSLayoutAttributeTop, NSLayoutAttributeLeft, NSLayoutAttributeBottom, NSLayoutAttributeRight
 */
- (YSMASConstraint * (^)(CGFloat inset))inset;

/**
 *	Modifies the NSLayoutConstraint constant,
 *  only affects YSMASConstraints in which the first item's NSLayoutAttribute is one of the following
 *  NSLayoutAttributeWidth, NSLayoutAttributeHeight
 */
- (YSMASConstraint * (^)(CGSize offset))sizeOffset;

/**
 *	Modifies the NSLayoutConstraint constant,
 *  only affects YSMASConstraints in which the first item's NSLayoutAttribute is one of the following
 *  NSLayoutAttributeCenterX, NSLayoutAttributeCenterY
 */
- (YSMASConstraint * (^)(CGPoint offset))centerOffset;

/**
 *	Modifies the NSLayoutConstraint constant
 */
- (YSMASConstraint * (^)(CGFloat offset))offset;

/**
 *  Modifies the NSLayoutConstraint constant based on a value type
 */
- (YSMASConstraint * (^)(NSValue *value))valueOffset;

/**
 *	Sets the NSLayoutConstraint multiplier property
 */
- (YSMASConstraint * (^)(CGFloat multiplier))multipliedBy;

/**
 *	Sets the NSLayoutConstraint multiplier to 1.0/dividedBy
 */
- (YSMASConstraint * (^)(CGFloat divider))dividedBy;

/**
 *	Sets the NSLayoutConstraint priority to a float or YSMASLayoutPriority
 */
- (YSMASConstraint * (^)(YSMASLayoutPriority priority))priority;

/**
 *	Sets the NSLayoutConstraint priority to YSMASLayoutPriorityLow
 */
- (YSMASConstraint * (^)(void))priorityLow;

/**
 *	Sets the NSLayoutConstraint priority to YSMASLayoutPriorityMedium
 */
- (YSMASConstraint * (^)(void))priorityMedium;

/**
 *	Sets the NSLayoutConstraint priority to YSMASLayoutPriorityHigh
 */
- (YSMASConstraint * (^)(void))priorityHigh;

/**
 *	Sets the constraint relation to NSLayoutRelationEqual
 *  returns a block which accepts one of the following:
 *    YSMASViewAttribute, UIView, NSValue, NSArray
 *  see readme for more details.
 */
- (YSMASConstraint * (^)(id attr))equalTo;

/**
 *	Sets the constraint relation to NSLayoutRelationGreaterThanOrEqual
 *  returns a block which accepts one of the following:
 *    YSMASViewAttribute, UIView, NSValue, NSArray
 *  see readme for more details.
 */
- (YSMASConstraint * (^)(id attr))greaterThanOrEqualTo;

/**
 *	Sets the constraint relation to NSLayoutRelationLessThanOrEqual
 *  returns a block which accepts one of the following:
 *    YSMASViewAttribute, UIView, NSValue, NSArray
 *  see readme for more details.
 */
- (YSMASConstraint * (^)(id attr))lessThanOrEqualTo;

/**
 *	Optional semantic property which has no effect but improves the readability of constraint
 */
- (YSMASConstraint *)with;

/**
 *	Optional semantic property which has no effect but improves the readability of constraint
 */
- (YSMASConstraint *)and;

/**
 *	Creates a new YSMASCompositeConstraint with the called attribute and reciever
 */
- (YSMASConstraint *)left;
- (YSMASConstraint *)top;
- (YSMASConstraint *)right;
- (YSMASConstraint *)bottom;
- (YSMASConstraint *)leading;
- (YSMASConstraint *)trailing;
- (YSMASConstraint *)width;
- (YSMASConstraint *)height;
- (YSMASConstraint *)centerX;
- (YSMASConstraint *)centerY;
- (YSMASConstraint *)baseline;

#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100)

- (YSMASConstraint *)firstBaseline;
- (YSMASConstraint *)lastBaseline;

#endif

#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000)

- (YSMASConstraint *)leftMargin;
- (YSMASConstraint *)rightMargin;
- (YSMASConstraint *)topMargin;
- (YSMASConstraint *)bottomMargin;
- (YSMASConstraint *)leadingMargin;
- (YSMASConstraint *)trailingMargin;
- (YSMASConstraint *)centerXWithinMargins;
- (YSMASConstraint *)centerYWithinMargins;

#endif


/**
 *	Sets the constraint debug name
 */
- (YSMASConstraint * (^)(id key))key;

// NSLayoutConstraint constant Setters
// for use outside of ysmas_updateConstraints/ysmas_makeConstraints blocks

/**
 *	Modifies the NSLayoutConstraint constant,
 *  only affects YSMASConstraints in which the first item's NSLayoutAttribute is one of the following
 *  NSLayoutAttributeTop, NSLayoutAttributeLeft, NSLayoutAttributeBottom, NSLayoutAttributeRight
 */
- (void)setInsets:(YSMASEdgeInsets)insets;

/**
 *	Modifies the NSLayoutConstraint constant,
 *  only affects YSMASConstraints in which the first item's NSLayoutAttribute is one of the following
 *  NSLayoutAttributeTop, NSLayoutAttributeLeft, NSLayoutAttributeBottom, NSLayoutAttributeRight
 */
- (void)setInset:(CGFloat)inset;

/**
 *	Modifies the NSLayoutConstraint constant,
 *  only affects YSMASConstraints in which the first item's NSLayoutAttribute is one of the following
 *  NSLayoutAttributeWidth, NSLayoutAttributeHeight
 */
- (void)setSizeOffset:(CGSize)sizeOffset;

/**
 *	Modifies the NSLayoutConstraint constant,
 *  only affects YSMASConstraints in which the first item's NSLayoutAttribute is one of the following
 *  NSLayoutAttributeCenterX, NSLayoutAttributeCenterY
 */
- (void)setCenterOffset:(CGPoint)centerOffset;

/**
 *	Modifies the NSLayoutConstraint constant
 */
- (void)setOffset:(CGFloat)offset;


// NSLayoutConstraint Installation support

#if TARGET_OS_MAC && !(TARGET_OS_IPHONE || TARGET_OS_TV)
/**
 *  Whether or not to go through the animator proxy when modifying the constraint
 */
@property (nonatomic, copy, readonly) YSMASConstraint *animator;
#endif

/**
 *  Activates an NSLayoutConstraint if it's supported by an OS. 
 *  Invokes install otherwise.
 */
- (void)activate;

/**
 *  Deactivates previously installed/activated NSLayoutConstraint.
 */
- (void)deactivate;

/**
 *	Creates a NSLayoutConstraint and adds it to the appropriate view.
 */
- (void)install;

/**
 *	Removes previously installed NSLayoutConstraint
 */
- (void)uninstall;

@end


/**
 *  Convenience auto-boxing macros for YSMASConstraint methods.
 *
 *  Defining YSMAS_SHORTHAND_GLOBALS will turn on auto-boxing for default syntax.
 *  A potential drawback of this is that the unprefixed macros will appear in global scope.
 */
#define ysmas_equalTo(...)                 equalTo(YSMASBoxValue((__VA_ARGS__)))
#define ysmas_greaterThanOrEqualTo(...)    greaterThanOrEqualTo(YSMASBoxValue((__VA_ARGS__)))
#define ysmas_lessThanOrEqualTo(...)       lessThanOrEqualTo(YSMASBoxValue((__VA_ARGS__)))

#define ysmas_offset(...)                  valueOffset(YSMASBoxValue((__VA_ARGS__)))


#ifdef YSMAS_SHORTHAND_GLOBALS

#define equalTo(...)                     ysmas_equalTo(__VA_ARGS__)
#define greaterThanOrEqualTo(...)        ysmas_greaterThanOrEqualTo(__VA_ARGS__)
#define lessThanOrEqualTo(...)           ysmas_lessThanOrEqualTo(__VA_ARGS__)

#define offset(...)                      ysmas_offset(__VA_ARGS__)

#endif


@interface YSMASConstraint (AutoboxingSupport)

/**
 *  Aliases to corresponding relation methods (for shorthand macros)
 *  Also needed to aid autocompletion
 */
- (YSMASConstraint * (^)(id attr))ysmas_equalTo;
- (YSMASConstraint * (^)(id attr))ysmas_greaterThanOrEqualTo;
- (YSMASConstraint * (^)(id attr))ysmas_lessThanOrEqualTo;

/**
 *  A dummy method to aid autocompletion
 */
- (YSMASConstraint * (^)(id offset))ysmas_offset;

@end
