//
//  LPRefreshIndicator.m
//  LPRefresh
//
//  Created by FineexMac on 16/1/6.
//  Copyright 漏 2016骞?LPiOS. All rights reserved.
//
//  浣滆€匞itHub涓婚〉 https://github.com/SwiftLiu
//  浣滆€呴偖绠?1062014109@qq.com
//  涓嬭浇閾炬帴 https://github.com/SwiftLiu/LPRefresh.git

#import "LPRefreshIndicator.h"

///涓婚棰滆壊
#define LPRefreshMainColor(_alpha) [UIColor colorWithWhite:0.7 alpha:_alpha]
///鍥剧墖璺緞
#define LPRefreshSrcName(file) [@"LPRefresh.bundle" stringByAppendingPathComponent:file]

///涓嬫媺鍒版鍋忕Щ閲忓紑濮嬫媺浼?const CGFloat LPBeganStretchOffset = 36;
///涓嬫媺鍒版鍋忕Щ閲忓紑濮嬪埛鏂?const CGFloat LPBeganRefreshOffset = 90;

const CGFloat LPRefreshMargin = 3;
const NSTimeInterval LPRefreshAnimateDuration = 0.5;

@interface LPRefreshIndicator ()
{
    //缁樺埗瑙嗗浘
    CALayer *drawLayer;
    //鎸囩ず鍣?    UIActivityIndicatorView *indicatorView;
    //鎻愮ず鏍囩
    UILabel *capionLabel;
    //鎸囩ず鍣ㄥ浘鏍?    UIImage *image;
    
    //鐘舵€?    BOOL refreshing;
    //鎵ц鎺у埗
    BOOL shouldDo;
    
    //鏄惁鍦ㄨ繘琛屽洖寮瑰姩鐢?    BOOL backing;
    //鍥炲脊鍔ㄧ敾缁撴潫绔嬪嵆鎵ц缁撴潫鐨勫姩鐢?    void (^backCompleteBlock)();
    
    //鍒锋柊鎴愬姛鎻愮ず
    NSAttributedString *capionSuccess;
    //鍒锋柊澶辫触鎻愮ず
    NSAttributedString *capionFail;
}
@end

@implementation LPRefreshIndicator

#pragma mark - 璁剧疆涓嬫媺鍋忕Щ閲?- (void)setPullProgress:(CGFloat)pullProgress
{
    if (pullProgress == _pullProgress) return;
    if (!refreshing) {
        //鈶犲紑濮嬫嫋鍑?        if (pullProgress <= LPBeganStretchOffset) {
            if (_pullProgress<=3 && pullProgress>3) {
                shouldDo = YES;
                capionLabel.alpha = 0;
                [self drawHeight:LPBeganStretchOffset];//缁樺埗鍦?            }
        }
        //鈶℃媺浼搁樁娈?        else if (pullProgress < LPBeganRefreshOffset) {
            if (shouldDo) [self drawHeight:pullProgress];//缁樺埗姗$毊绛?        }
        //鈶㈠紑濮嬪埛鏂?        else if (shouldDo) {
            shouldDo = NO;
            refreshing = YES;
            [self backAnimate:LPBeganRefreshOffset];//鍥炲脊鍔ㄧ敾
            if (_refreshBlock) _refreshBlock();//鎵ц鍒锋柊浠g爜
        }
    }
    //鈶e埛鏂扮姸鎬佷笅鍥炲脊闇€鍋滈】
    else if (_pullProgress > LPBeganStretchOffset && pullProgress < LPBeganStretchOffset) {
        [self superviewScrollTo:-LPBeganStretchOffset];//婊氬姩
        
    }
    _pullProgress = pullProgress;
    
    //楂樺害浣嶇疆
    CGRect frame = self.frame;
    frame.size.height = MAX(LPBeganStretchOffset, pullProgress);
    frame.origin.y = -frame.size.height;
    self.frame = frame;
}

#pragma mark - 姗$毊绛嬭嚜鍔ㄥ洖寮瑰姩鐢?- (void)backAnimate:(CGFloat)animateH
{
    backing = YES;//鍥炲脊鍔ㄧ敾鎵ц涓?    //姗$毊绛嬪洖寮?    CGFloat endOffset = LPBeganStretchOffset+15;//鍥炲脊缁撴潫鍋忕Щ閲?    if (animateH >= endOffset) {
        animateH -= 3;
        [self drawHeight:animateH];
        //寰幆璋冪敤
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.014 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [self backAnimate:animateH];
        });
    }
    //鏄剧ず鎸囩ず鍣?    else{
        drawLayer.contents = nil;
        [indicatorView startAnimating];
        
        backing = NO;//鍥炲脊鍔ㄧ敾缁撴潫
        if (backCompleteBlock) {
            backCompleteBlock();
            backCompleteBlock = nil;
        }
    }
}

#pragma mark - 缁撴潫鍒锋柊
- (void)refreshSuccess:(BOOL)isSuccess
{
    if (refreshing) {
        //姝e湪杩涜鍥炲脊鍔ㄧ敾鏃讹紝缁撴潫鍔ㄧ敾鏀惧湪鍥炲脊鍔ㄧ敾缁撴潫鍚庢墽琛?        if (backing) {
            __weak LPRefreshIndicator *weakSelf = self;
            backCompleteBlock = ^{
                refreshing = NO;
                [weakSelf endAnimate:isSuccess];
            };
        }
        //鏈繘琛屽洖寮瑰姩鐢绘椂锛岀洿鎺ユ墽琛岀粨鏉熷姩鐢?        else {
            refreshing = NO;
            [self endAnimate:isSuccess];
        }
    }
}

#pragma mark - 缁撴潫鍔ㄧ敾
- (void)endAnimate:(BOOL)isSuccess
{
    [indicatorView stopAnimating];
    
    capionLabel.attributedText = [self endCapion:isSuccess];
    [UIView animateWithDuration:0.8 animations:^{
        capionLabel.alpha = 1;
    } completion:^(BOOL finished) {
        if (finished && _pullProgress==LPBeganStretchOffset) {
            [self superviewScrollTo:0];//婊氬姩鍒伴《閮?        }
    }];
}

#pragma mark - 缁樺埗
- (void)drawHeight:(CGFloat)h
{
    //鍒濆鍖栫敾甯?    CGFloat screenScale = [UIScreen mainScreen].scale;
    CGSize size = drawLayer.bounds.size;
    UIGraphicsBeginImageContextWithOptions(size, NO, screenScale);
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    CGContextSaveGState(ctx);
    
    //鎷変几搴?    CGFloat s = (h-LPBeganStretchOffset) / (LPBeganRefreshOffset-LPBeganStretchOffset);
    // 鈶犵粯鍒舵鐨瓔閮ㄥ垎
    //闃村奖棰滆壊
    drawLayer.shadowColor = [UIColor colorWithWhite:0 alpha:.6+.4*s].CGColor;
    //濉厖棰滆壊
    CGColorRef color = LPRefreshMainColor(1).CGColor;
    if (refreshing) color = LPRefreshMainColor(.6+.4*s).CGColor;
    CGContextSetFillColorWithColor(ctx, color);
    //澶у渾鍗婂緞
    CGFloat w = size.width / 2.l;
    CGFloat R = w - w*.3 * (backing?1:s);
    //鍧愭爣绉诲姩鑷冲ぇ鍦嗗渾蹇?    CGContextTranslateCTM(ctx, w, w+LPRefreshMargin);
    //灏忓渾鍗婂緞
    CGFloat r = (backing?.4:1)*w*(1-s)+3*s;
    //灏忓渾鍦嗗績
    CGPoint o = CGPointMake(0, h-w-r-LPRefreshMargin*2);
    //鍚勬洸绾夸氦鐐?    double agl = M_PI_2 / 9.l;
    CGPoint a1 = CGPointMake(-R*cos(agl), R*sin(agl));
    CGPoint a2 = CGPointMake(-a1.x, a1.y);
//    CGPoint b1 = CGPointMake(-r, o.y);
    CGPoint b2 = CGPointMake(r, o.y);
    //璐濆灏旀洸绾挎帶鍒剁偣
    CGPoint c1 = CGPointMake(-r, o.y/2.l);
    CGPoint c2 = CGPointMake(-c1.x, c1.y);
    //璺緞
    CGContextMoveToPoint(ctx, a2.x, a2.y);
    CGContextAddArc(ctx, 0, 0, R, agl, 2*M_PI+agl, NO);
    CGContextAddQuadCurveToPoint(ctx, c2.x, c2.y, b2.x, b2.y);
    CGContextAddArc(ctx, o.x, o.y, r, 0, M_PI, NO);
    CGContextAddQuadCurveToPoint(ctx, c1.x, c1.y, a1.x, a1.y);
    //缁樺埗璺緞
    CGContextDrawPath(ctx, kCGPathFill);
    
    // 鈶$粯鍒跺浘鐗?    CGFloat wide = 2*R*0.7l;
    CGRect frame = CGRectMake(-wide/2.l, -wide/2.l, wide, wide);
    //鏃嬭浆鍧愭爣绯?    CGContextRotateCTM(ctx, s * M_PI*1.5);
    if (!image) image = [UIImage imageNamed:LPRefreshSrcName(@"LPRefresh_pull")];
    [image drawInRect:frame];
    
    //鎻愬彇缁樺埗鍥惧儚
    UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
    CGContextRestoreGState(ctx);
    CGContextRelease(ctx);
    UIGraphicsEndImageContext();
    drawLayer.contents = (__bridge id _Nullable)(img.CGImage);
}


#pragma mark - 閲嶅啓
- (instancetype)init
{
    self = [super init];
    if (self) {
        self.bounds = CGRectMake(0, 0, 0, LPBeganStretchOffset);
        self.clipsToBounds = YES;
        
        //鍥惧眰
        drawLayer = [CALayer layer];
        CGFloat wide = LPBeganStretchOffset-2*LPRefreshMargin;
        drawLayer.frame = CGRectMake(0, 0, wide, LPBeganRefreshOffset);
        [self.layer addSublayer:drawLayer];
        drawLayer.shadowRadius = 1;
        drawLayer.shadowOffset = CGSizeMake(0, 1);
        drawLayer.shadowOpacity = 0.1;
        
        //鎸囩ず鍣?        indicatorView = [UIActivityIndicatorView new];
        indicatorView.center = CGPointMake(0, LPBeganStretchOffset/2.l);
        indicatorView.color = [UIColor grayColor];
        [self addSubview:indicatorView];
        
        //鎻愮ず鏍囩
        capionLabel = [UILabel new];
        capionLabel.bounds = CGRectMake(0, 0, 300, 30);
        capionLabel.center = indicatorView.center;
        capionLabel.alpha = 0;
        capionLabel.textColor = [UIColor colorWithWhite:.45 alpha:1];
        capionLabel.textAlignment = NSTextAlignmentCenter;
        capionLabel.font = [UIFont systemFontOfSize:14];
        [self addSubview:capionLabel];
    }
    return self;
}

- (void)setFrame:(CGRect)frame
{
    if (self.frame.size.width != frame.size.width) {
        [self centerSub:frame.size.width];
    }
    [super setFrame:frame];
}

- (void)setBounds:(CGRect)bounds
{
    if (self.bounds.size.width != bounds.size.width) {
        [self centerSub:bounds.size.width];
    }
    [super setBounds:bounds];
}


//drawLayer灞呬腑
- (void)centerSub:(CGFloat)width
{
    CGRect frame = drawLayer.frame;
    frame.origin.x = (width - frame.size.width) / 2.l;
    drawLayer.frame = frame;
    
    CGPoint center = indicatorView.center;
    center.x = width / 2.l;
    indicatorView.center = center;
    capionLabel.center = center;
}


#pragma mark - 杈呭姪鏂规硶
//婊氬姩
- (void)superviewScrollTo:(CGFloat)offsetY
{
    UIScrollView *scrollView = (UIScrollView *)[self superview];
    if (scrollView) {
        CGPoint offset = scrollView.contentOffset;
        offset.y = offsetY;
        [scrollView setContentOffset:offset animated:YES];
    }
}

//鎻愮ず鏂囧瓧
- (NSAttributedString *)endCapion:(BOOL)isSuccess
{
    if (isSuccess) {
        if (!capionSuccess) {
            capionSuccess = [self attributedString:@"鍒锋柊鎴愬姛"
                                           imgName:LPRefreshSrcName(@"LPRefresh_ok")];
        }
        return capionSuccess;
    }else {
        if (!capionFail) {
            capionFail = [self attributedString:@"鍒锋柊澶辫触"
                                        imgName:LPRefreshSrcName(@"LPRefresh_fail")];
        }
        return capionFail;
    }
}

- (NSAttributedString *)attributedString:(NSString *)capion imgName:(NSString *)imgName
{
    //鎻愮ず鍥炬爣
    NSTextAttachment *attachment = [NSTextAttachment new];
    attachment.image = [UIImage imageNamed:imgName];
    CGSize size = attachment.image.size;
    attachment.bounds = CGRectMake(0, -2.5l, size.width, size.height);
    NSAttributedString *imgAttrStr = [NSAttributedString attributedStringWithAttachment:attachment];
    //鎻愮ず鏂囧瓧
    NSString *str = [NSString stringWithFormat:@" %@", capion];
    NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] initWithString:str];
    [attrString insertAttributedString:imgAttrStr atIndex:0];
    return attrString;
}

@end
// 鐗堟潈灞炰簬鍘熶綔鑰?// http://code4app.com (cn) http://code4app.net (en)
// 鍙戝竷浠g爜浜庢渶涓撲笟鐨勬簮鐮佸垎浜綉绔? Code4App.com