//
//  UIView+XVAdd.m
//  fastservice
//
//  Created by xuning on 2/3/24.
//  Copyright © 2024 FastService. All rights reserved.
//

#import "UIView+XVAdd.h"
#import <objc/runtime.h>
static const char * kHitEdgeInsets = "hitEdgeInsets";
static const char * kHitScale      = "hitScale";
static const char * kHitWidthScale      = "hitWidthScale";
static const char * kHitHeightScale      = "hitHeightScale";
static const char *UIControl_acceptEventInterval = "UIControl_acceptEventInterval";
@implementation UIView (XVAdd)
#pragma mark - 设置部分圆角
/**
 *  设置部分圆角(绝对布局)
 *
 *  @param corners 需要设置为圆角的角 UIRectCornerTopLeft | UIRectCornerTopRight | UIRectCornerBottomLeft | UIRectCornerBottomRight | UIRectCornerAllCorners
 *  @param radii   需要设置的圆角大小 例如 CGSizeMake(20.0f, 20.0f)
 */
- (void)addRoundedCorners:(UIRectCorner)corners
                withRadii:(CGSize)radii {
    
    UIBezierPath* rounded = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:corners cornerRadii:radii];
    CAShapeLayer* shape = [[CAShapeLayer alloc] init];
    [shape setPath:rounded.CGPath];
    
    self.layer.mask = shape;
}

/**
 *  设置部分圆角(相对布局)
 *
 *  @param corners 需要设置为圆角的角 UIRectCornerTopLeft | UIRectCornerTopRight | UIRectCornerBottomLeft | UIRectCornerBottomRight | UIRectCornerAllCorners
 *  @param radii   需要设置的圆角大小 例如 CGSizeMake(20.0f, 20.0f)
 *  @param rect    需要设置的圆角view的rect
 */
- (void)addRoundedCorners:(UIRectCorner)corners
                withRadii:(CGSize)radii
                 viewRect:(CGRect)rect {
    
    UIBezierPath* rounded = [UIBezierPath bezierPathWithRoundedRect:rect byRoundingCorners:corners cornerRadii:radii];
    CAShapeLayer* shape = [[CAShapeLayer alloc] init];
    [shape setPath:rounded.CGPath];
    
    self.layer.mask = shape;
}
@end

@implementation UILabel (XVAdd)

- (instancetype)initWithText:(NSString *)text textColor:(UIColor *)color textAlignment:(NSTextAlignment)alignment fontSize:(CGFloat)size {
    UILabel *customLabel = [[UILabel alloc]init];
    customLabel.text = text;
    customLabel.textColor = color;
    if (alignment) {
        customLabel.textAlignment = alignment;
    }
    customLabel.font = [UIFont systemFontOfSize:size];
    [customLabel sizeToFit];
    return customLabel;
}

+ (void)changeLineSpaceForLabel:(UILabel *)label WithSpace:(float)space {
    
    NSString *labelText = label.text;
    NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:labelText];
    NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
    [paragraphStyle setLineSpacing:space];
    [attributedString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, [labelText length])];
    label.attributedText = attributedString;
    label.lineBreakMode = NSLineBreakByTruncatingTail;
    [label sizeToFit];
    
}

+ (void)changeWordSpaceForLabel:(UILabel *)label WithSpace:(float)space {
    
    NSString *labelText = label.text;
    NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:labelText attributes:@{NSKernAttributeName:@(space)}];
    NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
    [attributedString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, [labelText length])];
    label.attributedText = attributedString;
    [label sizeToFit];
    
}

+ (void)changeSpaceForLabel:(UILabel *)label withLineSpace:(float)lineSpace WordSpace:(float)wordSpace {
    
    NSString *labelText = label.text;
    NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:labelText attributes:@{NSKernAttributeName:@(wordSpace)}];
    NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
    [paragraphStyle setLineSpacing:lineSpace];
    [attributedString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, [labelText length])];
    label.attributedText = attributedString;
    [label sizeToFit];
    
}



@end

@implementation UIButton (XVAdd)

// 在load时执行hook
+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Class class = [self class];
        //分别获取
        SEL beforeSelector = @selector(sendAction:to:forEvent:);
        SEL afterSelector = @selector(cs_sendAction:to:forEvent:);
        
        Method beforeMethod = class_getInstanceMethod(class, beforeSelector);
        Method afterMethod = class_getInstanceMethod(class, afterSelector);
        //先尝试给原来的方法添加实现，如果原来的方法不存在就可以添加成功。返回为YES，否则
        //返回为NO。
        //UIButton 真的没有sendAction方法的实现，这是继承了UIControl的而已，UIControl才真正的实现了。
        BOOL didAddMethod =
        class_addMethod(class,
                        beforeSelector,
                        method_getImplementation(afterMethod),
                        method_getTypeEncoding(afterMethod));
        NSLog(@"%d",didAddMethod);
        if (didAddMethod) {
            // 如果之前不存在，但是添加成功了，此时添加成功的是cs_sendAction方法的实现
            // 这里只需要方法替换
            class_replaceMethod(class,
                                afterSelector,
                                method_getImplementation(beforeMethod),
                                method_getTypeEncoding(beforeMethod));
        } else {
            //本来如果存在就进行交换
            method_exchangeImplementations(afterMethod, beforeMethod);
        }
    });
}
- (void)cs_sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event {
    if ([NSDate date].timeIntervalSince1970 - self.cs_acceptEventTime < self.cs_acceptEventInterval) {
        return;
    }
    if (self.cs_acceptEventInterval > 0) {
        self.cs_acceptEventTime = [NSDate date].timeIntervalSince1970;
    }
    [self cs_sendAction:action to:target forEvent:event];
    
}

- (NSTimeInterval)cs_acceptEventInterval {
    return  [objc_getAssociatedObject(self, UIControl_acceptEventInterval) doubleValue];
}

- (void)setCs_acceptEventInterval:(NSTimeInterval)cs_acceptEventInterval {
    objc_setAssociatedObject(self, UIControl_acceptEventInterval, @(cs_acceptEventInterval), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

static const char *UIControl_acceptEventTime = "UIControl_acceptEventTime";

- (NSTimeInterval)cs_acceptEventTime {
    return  [objc_getAssociatedObject(self, UIControl_acceptEventTime) doubleValue];
}

- (void)setCs_acceptEventTime:(NSTimeInterval)cs_acceptEventTime {
    objc_setAssociatedObject(self, UIControl_acceptEventTime, @(cs_acceptEventTime), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}


- (void)setHighlighted:(BOOL)highlighted {
    
}

#pragma mark - set Method
-(void)setHitEdgeInsets:(UIEdgeInsets)hitEdgeInsets{
    NSValue *value = [NSValue value:&hitEdgeInsets withObjCType:@encode(UIEdgeInsets)];
    objc_setAssociatedObject(self,kHitEdgeInsets, value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

-(void)setHitScale:(CGFloat)hitScale{
    CGFloat width = self.bounds.size.width * hitScale;
    CGFloat height = self.bounds.size.height * hitScale;
    self.hitEdgeInsets = UIEdgeInsetsMake(-height, -width,-height, -width);
    objc_setAssociatedObject(self, kHitScale, @(hitScale), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}


-(void)setHitWidthScale:(CGFloat)hitWidthScale{
    CGFloat width = self.bounds.size.width * hitWidthScale;
    CGFloat height = self.bounds.size.height ;
    self.hitEdgeInsets = UIEdgeInsetsMake(-height, -width,-height, -width);
    objc_setAssociatedObject(self, kHitWidthScale, @(hitWidthScale), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}



-(void)setHitHeightScale:(CGFloat)hitHeightScale{
    CGFloat width = self.bounds.size.width;
    CGFloat height = self.bounds.size.height * hitHeightScale ;
    self.hitEdgeInsets = UIEdgeInsetsMake(-height, -width,-height, -width);
    objc_setAssociatedObject(self, kHitHeightScale, @(hitHeightScale), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}


#pragma mark - get Method
-(UIEdgeInsets)hitEdgeInsets{
    NSValue *value = objc_getAssociatedObject(self, kHitEdgeInsets);
    UIEdgeInsets edgeInsets;
    [value getValue:&edgeInsets];
    return value ? edgeInsets:UIEdgeInsetsZero;
}

-(CGFloat)hitScale{
    return [objc_getAssociatedObject(self, kHitScale) floatValue];
}

-(CGFloat)hitWidthScale{
    return [objc_getAssociatedObject(self, kHitWidthScale) floatValue];
}

-(CGFloat)hitHeightScale{
    return [objc_getAssociatedObject(self, kHitHeightScale) floatValue];
}



#pragma mark - override super method
-(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event{
    //如果 button 边界值无变化  失效 隐藏 或者透明 直接返回
    if(UIEdgeInsetsEqualToEdgeInsets(self.hitEdgeInsets, UIEdgeInsetsZero) || !self.enabled || self.hidden || self.alpha == 0 ) {
        return [super pointInside:point withEvent:event];
    }else{
        CGRect relativeFrame = self.bounds;
        CGRect hitFrame = UIEdgeInsetsInsetRect(relativeFrame, self.hitEdgeInsets);
        return CGRectContainsPoint(hitFrame, point);
    }
}



- (instancetype)initWithTitle:(NSString *)title fontSize:(CGFloat)size titleColor:(UIColor *)titleColor normalImageName:(NSString *)imageName selectedImgName:(NSString *)selectedImgName backgroundColor:(UIColor *)backgroundColor {

    UIButton *customButton = [[UIButton alloc]init];
    
    [customButton setTitle:title forState:UIControlStateNormal];
    customButton.titleLabel.font = [UIFont systemFontOfSize:size];
    [customButton setTitleColor:titleColor forState:UIControlStateNormal];
    if (imageName) {
        [customButton setImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal];
    }
    if (selectedImgName) {
        [customButton setImage:[UIImage imageNamed:selectedImgName] forState:UIControlStateSelected];
    }
    
    if (backgroundColor) {
        customButton.backgroundColor = backgroundColor;
    }
    
    return customButton;
}

- (instancetype)initWithTitle:(NSString *)title fontSize:(CGFloat)size normalTitleColor:(UIColor *)normalTitleColor selectTitleColor:(UIColor *)selectTitleColor normalImgColor:(UIColor *)normalImgColor selectedImgColor:(UIColor *)selectedImgColor {
    UIButton *customButton = [UIButton buttonWithType:UIButtonTypeCustom];
    
    [customButton setTitle:title forState:UIControlStateNormal];
    customButton.titleLabel.font = [UIFont systemFontOfSize:size];
    [customButton setTitleColor:normalTitleColor forState:UIControlStateNormal];
    [customButton setTitleColor:selectTitleColor forState:UIControlStateSelected];
    if (normalImgColor) {
        [customButton setBackgroundImage:[UIImage imageWithColor:normalImgColor] forState:UIControlStateNormal];
    }
    if (selectedImgColor) {
        [customButton setBackgroundImage:[UIImage imageWithColor:selectedImgColor] forState:UIControlStateSelected];
    }
    
    return customButton;

    
}

- (instancetype)initWithTitle:(NSString *)title fontSize:(CGFloat)size titleColor:(UIColor *)titleColor bgColor:(UIColor *)bgColor {
    UIButton *customButton = [UIButton buttonWithType:UIButtonTypeCustom];
    
    [customButton setTitle:title forState:UIControlStateNormal];
    customButton.titleLabel.font = [UIFont systemFontOfSize:size];
    [customButton setTitleColor:titleColor forState:UIControlStateNormal];
    if (bgColor) {
        [customButton setBackgroundColor:bgColor];
    }
    return customButton;

    
}
- (instancetype)initWithNormalImageName:(NSString *)imageName selectedImgName:(NSString *)selectedImgName {
 
    UIButton *customButton = [[UIButton alloc]init];
    
    if (imageName) {
        [customButton setImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal];
    }
    if (selectedImgName) {
        [customButton setImage:[UIImage imageNamed:selectedImgName] forState:UIControlStateSelected];
    }
    
    return customButton;
}

- (void)setForceRightToLeft:(CGFloat)spacing forState:(UIControlState)state {
    if ([[UIDevice currentDevice].systemVersion floatValue] < 9.0) {
        NSString *title = [self titleForState:state];
        UIImage *image = [self imageForState:state];
        if (title && image) {
            [self setTitleEdgeInsets:UIEdgeInsetsMake(0, -image.size.width - spacing / 2, 0, image.size.width)];
            CGSize labelSize = [title sizeWithAttributes:@{NSFontAttributeName:self.titleLabel.font}];
            [self setImageEdgeInsets:UIEdgeInsetsMake(0, labelSize.width, 0, -labelSize.width - spacing / 2)];
        }
    } else {
        self.semanticContentAttribute = UISemanticContentAttributeForceRightToLeft;
        [self setTitleEdgeInsets:UIEdgeInsetsMake(0, -spacing / 2, 0, 0)];
        [self setImageEdgeInsets:UIEdgeInsetsMake(0, 0, 0, -spacing / 2)];
    }
}

@end



@implementation UIImageView (XVAdd)

- (instancetype)initWithImageName:(NSString *)imageNamed {
    UIImageView *customImageView = [[UIImageView alloc]init];
    customImageView.image = [UIImage imageNamed:imageNamed];
    return customImageView;
    
}

@end
