//
// SMModernCalloutView.m
// Project
//
// Created by haibara on 2/22/17.
//
//

#import "SMModernCalloutView.h"
#import <objc/message.h>
#import "UIConstants.h"
#import <PureLayout/PureLayout.h>

#define COMFORTABLE_MARGIN 10

@interface SMCalloutView ()
@property (nonatomic, strong) UIButton *containerView;
@property (nonatomic, strong) UILabel *titleLabel, *subtitleLabel;
@property (nonatomic, assign) SMCalloutArrowDirection currentArrowDirection;
- (void)rebuildSubviews;
- (UIView *)titleViewOrDefault;
- (UIView *)subtitleViewOrDefault;
@end

@interface SMModernCalloutView () {
	SMCalloutArrowDirection _restorationArrowDirection;
}
@property (nonatomic, strong) NSArray *upConstraints;
@property (nonatomic, strong) NSArray *downConstraints;
@end

@implementation SMModernCalloutView

@synthesize currentArrowDirection = _currentArrowDirection;

- (instancetype)init {
	if (self = [super init]) {
		self.textLabel = [[UILabel alloc] init];
		self.textLabel.font = [UIConstants defaultTableViewCellTextLabelFont:UITableViewCellStyleSubtitle];
		self.detailTextLabel = [[UILabel alloc] init];
		self.detailTextLabel.font = [UIConstants defaultTableViewCellDetailTextLabelFont:UITableViewCellStyleSubtitle];
	}
	return self;
}

- (void)layoutSubviews {
	struct objc_super s;
	s.receiver = self;
	s.super_class = [UIView class];
	objc_msgSendSuper(&s, @selector(layoutSubviews));
}

- (void)updateConstraints {
	if (self.currentArrowDirection == SMCalloutArrowDirectionUp) {
		[self.upConstraints autoInstallConstraints];
	} else if (self.currentArrowDirection == SMCalloutArrowDirectionDown) {
		[self.downConstraints autoInstallConstraints];
	}
	if (_restorationArrowDirection != self.currentArrowDirection) {
		if (_restorationArrowDirection == SMCalloutArrowDirectionUp) {
			[self.upConstraints autoRemoveConstraints];
		} else if (_restorationArrowDirection == SMCalloutArrowDirectionDown) {
			[self.downConstraints autoRemoveConstraints];
		}
	}
	[super updateConstraints];
}

- (CGSize)sizeThatFits:(CGSize)size {
	// NSLog(@"sizeThatFits from %@", NSStringFromCGSize(size));
	CGSize fittingSize = [self contentFittingSize:size];
	CGFloat width = fittingSize.width;
	CGFloat height = fittingSize.height;
	if (self.leftAccessoryView) {
		width += CGRectGetWidth(self.leftAccessoryView.frame) + self.contentViewInset.right;
		height = MAX(CGRectGetHeight(self.leftAccessoryView.frame), height);
	}
	if (self.rightAccessoryView) {
		width += CGRectGetWidth(self.rightAccessoryView.frame) + self.contentViewInset.left;
		height = MAX(CGRectGetHeight(self.rightAccessoryView.frame), height);
	}
	width += self.contentViewInset.left + self.contentViewInset.right;
	height += self.contentViewInset.top + self.contentViewInset.bottom;
	height += self.backgroundView.anchorHeight;
	// NSLog(@"sizeThatFits to %@", NSStringFromCGSize(CGSizeMake(width, height)));
	return CGSizeMake(width, height);
}

- (CGSize)intrinsicContentSize {
	return CGSizeMake(UIViewNoIntrinsicMetric, UIViewNoIntrinsicMetric);
}

#pragma mark - Proprty

- (void)setCurrentArrowDirection:(SMCalloutArrowDirection)currentArrowDirection {
	_restorationArrowDirection = _currentArrowDirection;
	_currentArrowDirection = currentArrowDirection;
}

#pragma mark - Protected

- (NSString *)title {
	return self.textLabel.text;
}

- (void)setTitle:(NSString *)title {
	self.textLabel.text = title;
}

- (NSString *)subtitle {
	return self.detailTextLabel.text;
}

- (void)setSubtitle:(NSString *)subtitle {
	self.detailTextLabel.text = subtitle;
}

- (UIView *)titleViewOrDefault {
	if (self.titleView) {
		return self.titleView;
	}
	return self.textLabel;
}

- (UIView *)subtitleViewOrDefault {
	if (self.subtitleView) {
		return self.titleView;
	}
	return self.detailTextLabel;
}

- (void)rebuildSubviews {
	[super rebuildSubviews];

	[self.backgroundView autoPinEdgesToSuperviewEdges];
	[self.containerView autoPinEdgesToSuperviewEdges];
	[self.leftAccessoryView autoPinEdgeToSuperviewEdge:ALEdgeLeft withInset:self.contentViewInset.left];
	[self.rightAccessoryView autoPinEdgeToSuperviewEdge:ALEdgeRight withInset:self.contentViewInset.right];
	[NSLayoutConstraint autoSetPriority:UILayoutPriorityRequired forConstraints:^{
		[self.leftAccessoryView autoSetContentCompressionResistancePriorityForAxis:ALAxisHorizontal];
		[self.rightAccessoryView autoSetContentCompressionResistancePriorityForAxis:ALAxisHorizontal];
	}];
	if (self.leftAccessoryView) {
		[self.titleViewOrDefault autoPinEdge:ALEdgeLeft toEdge:ALEdgeRight ofView:self.leftAccessoryView withOffset:self.contentViewInset.left];
		[self.subtitleViewOrDefault autoPinEdge:ALEdgeLeft toEdge:ALEdgeRight ofView:self.leftAccessoryView withOffset:self.contentViewInset.left];
	} else {
		[self.titleViewOrDefault autoPinEdgeToSuperviewEdge:ALEdgeLeft withInset:self.contentViewInset.left];
		[self.subtitleViewOrDefault autoPinEdgeToSuperviewEdge:ALEdgeLeft withInset:self.contentViewInset.left];
	}
	if (self.rightAccessoryView) {
		[self.rightAccessoryView autoPinEdge:ALEdgeLeft toEdge:ALEdgeRight ofView:self.titleViewOrDefault withOffset:self.contentViewInset.right];
		[self.rightAccessoryView autoPinEdge:ALEdgeLeft toEdge:ALEdgeRight ofView:self.subtitleViewOrDefault withOffset:self.contentViewInset.right];
	} else {
		[self.titleViewOrDefault autoPinEdgeToSuperviewEdge:ALEdgeRight withInset:self.contentViewInset.right];
		[self.subtitleViewOrDefault autoPinEdgeToSuperviewEdge:ALEdgeRight withInset:self.contentViewInset.right];
	}
	[self.subtitleViewOrDefault autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:self.titleViewOrDefault];

	self.upConstraints = [NSLayoutConstraint autoCreateConstraintsWithoutInstalling:^(void) {
		[self.leftAccessoryView autoAlignAxis:ALAxisHorizontal toSameAxisOfView:self.containerView withOffset:self.backgroundView.anchorHeight / 2];
		[self.rightAccessoryView autoAlignAxis:ALAxisHorizontal toSameAxisOfView:self.containerView withOffset:self.backgroundView.anchorHeight / 2];
		[self.titleViewOrDefault autoPinEdgeToSuperviewEdge:ALEdgeTop withInset:self.contentViewInset.top + self.backgroundView.anchorHeight];
		[self.subtitleViewOrDefault autoPinEdgeToSuperviewEdge:ALEdgeBottom withInset:self.contentViewInset.bottom];
	}];
	self.downConstraints = [NSLayoutConstraint autoCreateConstraintsWithoutInstalling:^(void) {
		[self.leftAccessoryView autoAlignAxis:ALAxisHorizontal toSameAxisOfView:self.containerView withOffset:-1 * self.backgroundView.anchorHeight / 2];
		[self.rightAccessoryView autoAlignAxis:ALAxisHorizontal toSameAxisOfView:self.containerView withOffset:-1 * self.backgroundView.anchorHeight / 2];
		[self.titleViewOrDefault autoPinEdgeToSuperviewEdge:ALEdgeTop withInset:self.contentViewInset.top];
		[self.subtitleViewOrDefault autoPinEdgeToSuperviewEdge:ALEdgeBottom withInset:self.contentViewInset.bottom + self.backgroundView.anchorHeight];
	}];
}

- (CGFloat)calloutContainerHeight {
	CGSize fittingSize = [self contentFittingSize:self.bounds.size];
	CGFloat height = fittingSize.height;
	height += self.contentViewInset.top + self.contentViewInset.bottom;
	return height;
}

#pragma mark - Private

- (CGFloat)contentLayoutWidth:(CGFloat)width {
	if (self.leftAccessoryView) {
		width -= CGRectGetWidth(self.leftAccessoryView.frame) + self.contentViewInset.right;
	}
	if (self.rightAccessoryView) {
		width -= CGRectGetWidth(self.rightAccessoryView.frame) + self.contentViewInset.left;
	}
	width -= self.contentViewInset.left + self.contentViewInset.right;
	return width;
}

- (CGSize)contentFittingSize:(CGSize)size {
	CGFloat width = 0;
	CGFloat height = 0;
	CGFloat layoutWidth = [self contentLayoutWidth:size.width];
	if (self.contentView) {
		CGSize fittingSize = [self.contentView sizeThatFits:CGSizeMake(layoutWidth, CGFLOAT_MAX)];
		width = fittingSize.width;
		height = fittingSize.height;
	} else {
		if (self.titleViewOrDefault) {
			CGSize fittingSize = [self.titleViewOrDefault sizeThatFits:CGSizeMake(layoutWidth, CGFLOAT_MAX)];
			width = MAX(width, fittingSize.width);
			height += fittingSize.height;
		}
		if (self.subtitleViewOrDefault) {
			CGSize fittingSize = [self.subtitleViewOrDefault sizeThatFits:CGSizeMake(layoutWidth, CGFLOAT_MAX)];
			width = MAX(width, fittingSize.width);
			height += fittingSize.height;
		}
	}
	return CGSizeMake(width, height);
}

@end
