/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

#import <UIKit/UIKit.h>
#import <yoga/YGEnums.h>
#import <yoga/YGMacros.h>
#import <yoga/Yoga.h>

YG_EXTERN_C_BEGIN

extern YGValue YGPointValue(CGFloat value) NS_SWIFT_UNAVAILABLE(
    "Use the swift Int and FloatingPoint extensions instead");
extern YGValue YGPercentValue(CGFloat value) NS_SWIFT_UNAVAILABLE(
    "Use the swift Int and FloatingPoint extensions instead");

YG_EXTERN_C_END

typedef NS_OPTIONS(NSInteger, YGDimensionFlexibility) {
  YGDimensionFlexibilityFlexibleWidth = 1 << 0,
  YGDimensionFlexibilityFlexibleHeight = 1 << 1,
};

@interface YGLayout : NSObject

/**
 Make default init unavailable, as it will not initialise YGNode which is
 required for the setters and getters of YGLayout's properties to work properly.
*/
- (instancetype)init
    __attribute__((unavailable("you are not meant to initialise YGLayout")));

/**
 Make default init unavailable, as it will not initialise YGNode which is
 required for the setters and getters of YGLayout's properties to work properly.
 */
+ (instancetype)new
    __attribute__((unavailable("you are not meant to initialise YGLayout")));

/**
  The property that decides if we should include this view when calculating
  layout. Defaults to YES.
 */
@property(nonatomic, readwrite, assign, setter=setIncludedInLayout:)
    BOOL isIncludedInLayout;

/**
 The property that decides during layout/sizing whether or not styling
 properties should be applied. Defaults to NO.
 */
@property(nonatomic, readwrite, assign, setter=setEnabled:) BOOL isEnabled;

@property(nonatomic, readwrite, assign) YGDirection direction;
@property(nonatomic, readwrite, assign) YGFlexDirection flexDirection;
@property(nonatomic, readwrite, assign) YGJustify justifyContent;
@property(nonatomic, readwrite, assign) YGAlign alignContent;
@property(nonatomic, readwrite, assign) YGAlign alignItems;
@property(nonatomic, readwrite, assign) YGAlign alignSelf;
@property(nonatomic, readwrite, assign) YGPositionType position;
@property(nonatomic, readwrite, assign) YGWrap flexWrap;
@property(nonatomic, readwrite, assign) YGOverflow overflow;
@property(nonatomic, readwrite, assign) YGDisplay display;

@property(nonatomic, readwrite, assign) CGFloat flex;
@property(nonatomic, readwrite, assign) CGFloat flexGrow;
@property(nonatomic, readwrite, assign) CGFloat flexShrink;
@property(nonatomic, readwrite, assign) YGValue flexBasis;

@property(nonatomic, readwrite, assign) YGValue left;
@property(nonatomic, readwrite, assign) YGValue top;
@property(nonatomic, readwrite, assign) YGValue right;
@property(nonatomic, readwrite, assign) YGValue bottom;
@property(nonatomic, readwrite, assign) YGValue start;
@property(nonatomic, readwrite, assign) YGValue end;

@property(nonatomic, readwrite, assign) YGValue marginLeft;
@property(nonatomic, readwrite, assign) YGValue marginTop;
@property(nonatomic, readwrite, assign) YGValue marginRight;
@property(nonatomic, readwrite, assign) YGValue marginBottom;
@property(nonatomic, readwrite, assign) YGValue marginStart;
@property(nonatomic, readwrite, assign) YGValue marginEnd;
@property(nonatomic, readwrite, assign) YGValue marginHorizontal;
@property(nonatomic, readwrite, assign) YGValue marginVertical;
@property(nonatomic, readwrite, assign) YGValue margin;

@property(nonatomic, readwrite, assign) YGValue paddingLeft;
@property(nonatomic, readwrite, assign) YGValue paddingTop;
@property(nonatomic, readwrite, assign) YGValue paddingRight;
@property(nonatomic, readwrite, assign) YGValue paddingBottom;
@property(nonatomic, readwrite, assign) YGValue paddingStart;
@property(nonatomic, readwrite, assign) YGValue paddingEnd;
@property(nonatomic, readwrite, assign) YGValue paddingHorizontal;
@property(nonatomic, readwrite, assign) YGValue paddingVertical;
@property(nonatomic, readwrite, assign) YGValue padding;

@property(nonatomic, readwrite, assign) CGFloat borderLeftWidth;
@property(nonatomic, readwrite, assign) CGFloat borderTopWidth;
@property(nonatomic, readwrite, assign) CGFloat borderRightWidth;
@property(nonatomic, readwrite, assign) CGFloat borderBottomWidth;
@property(nonatomic, readwrite, assign) CGFloat borderStartWidth;
@property(nonatomic, readwrite, assign) CGFloat borderEndWidth;
@property(nonatomic, readwrite, assign) CGFloat borderWidth;

@property(nonatomic, readwrite, assign) YGValue width;
@property(nonatomic, readwrite, assign) YGValue height;
@property(nonatomic, readwrite, assign) YGValue minWidth;
@property(nonatomic, readwrite, assign) YGValue minHeight;
@property(nonatomic, readwrite, assign) YGValue maxWidth;
@property(nonatomic, readwrite, assign) YGValue maxHeight;

// Yoga specific properties, not compatible with flexbox specification
@property(nonatomic, readwrite, assign) CGFloat aspectRatio;

/**
 Get the resolved direction of this node. This won't be YGDirectionInherit
 */
@property(nonatomic, readonly, assign) YGDirection resolvedDirection;

/**
 Perform a layout calculation and update the frames of the views in the
 hierarchy with the results. If the origin is not preserved, the root view's
 layout results will applied from {0,0}.
 */
- (void)applyLayoutPreservingOrigin:(BOOL)preserveOrigin
    NS_SWIFT_NAME(applyLayout(preservingOrigin:));

/**
 Perform a layout calculation and update the frames of the views in the
 hierarchy with the results. If the origin is not preserved, the root view's
 layout results will applied from {0,0}.
 */
- (void)applyLayoutPreservingOrigin:(BOOL)preserveOrigin
               dimensionFlexibility:(YGDimensionFlexibility)dimensionFlexibility
    NS_SWIFT_NAME(applyLayout(preservingOrigin:dimensionFlexibility:));

/**
 Returns the size of the view if no constraints were given. This could
 equivalent to calling [self sizeThatFits:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX)];
 */
@property(nonatomic, readonly, assign) CGSize intrinsicSize;

/**
  Returns the size of the view based on provided constraints. Pass NaN for an
  unconstrained dimension.
 */
- (CGSize)calculateLayoutWithSize:(CGSize)size
    NS_SWIFT_NAME(calculateLayout(with:));

/**
 Returns the number of children that are using Flexbox.
 */
@property(nonatomic, readonly, assign) NSUInteger numberOfChildren;

/**
 Return a BOOL indiciating whether or not we this node contains any subviews
 that are included in Yoga's layout.
 */
@property(nonatomic, readonly, assign) BOOL isLeaf;

/**
 Return's a BOOL indicating if a view is dirty. When a node is dirty
 it usually indicates that it will be remeasured on the next layout pass.
 */
@property(nonatomic, readonly, assign) BOOL isDirty;

/**
 Mark that a view's layout needs to be recalculated. Only works for leaf views.
 */
- (void)markDirty;

@end
