//
//  RefreshAnimator.swift
//  LegendTeam
//
//  Created by lym on 2021/12/27.
//

import Foundation
import Lottie
import MJRefresh
import UIKit

@objcMembers class RefreshHeaderAnimator: MJRefreshHeader {
    var offsetStatusBarHeight: Bool = false
    
    private lazy var animationView: LottieAnimationView = {
        let animation = LottieAnimation.named("single_ring")
        let animationView = LottieAnimationView(animation: animation)
        
        
        animationView.contentMode = .scaleAspectFit
        animationView.loopMode = .loop
        animationView.backgroundBehavior = .pauseAndRestore
        animationView.backgroundColor = .clear
        animationView.size = CGSize(width: 16, height: 16)
        addSubview(animationView)
        return animationView
    }()

    private let kMaxHeaderPanHeight: CGFloat = 50.0

    override func prepare() {
        super.prepare()
        animationView.isHidden = false
        mj_h = kMaxHeaderPanHeight
        mj_w = UIScreen.width
    }

    override func placeSubviews() {
        super.placeSubviews()

        if animationView.mj_x == 0 {
            if offsetStatusBarHeight {
                mj_h = kMaxHeaderPanHeight + UIWindow.statusBarHeight
            } else {
                mj_h = kMaxHeaderPanHeight
            }
        }

        animationView.center = CGPoint(x: mj_w / 2, y: mj_h / 2)
        if offsetStatusBarHeight {
            animationView.mj_y = 15 + UIWindow.statusBarHeight
        } else {
            animationView.mj_y = 15
        }
    }

    override var state: MJRefreshState {
        willSet {
            guard state != newValue else {
                return
            }
        }
        didSet {
            switch state {
            case .willRefresh:
                self.animationView.alpha = 1
            case .refreshing:
                DispatchQueue.main.async { [weak self] in
                    self?.animationView.alpha = 1
                    self?.animationView.play()
                }
            case .pulling:
                let generator = UIImpactFeedbackGenerator(style: .light)
                generator.prepare()
                generator.impactOccurred()
            case .idle:
                DispatchQueue.main.async {  [weak self] in
                    self?.animationView.alpha = 0.6
                    self?.animationView.currentProgress = 0
                    self?.animationView.stop()
                }
                
            default:
                if !(oldValue == .refreshing) {
                    animationView.stop()
                }
            }
        }
    }

    override func scrollViewContentOffsetDidChange(_ change: [AnyHashable: Any]?) {
        super.scrollViewContentOffsetDidChange(change)

        if animationView.isAnimationPlaying {
            return
        }

        switch state {
        case .idle, .pulling:
            guard let dic = change else {
                return
            }
            guard let value = dic[NSKeyValueChangeKey.newKey] as? NSValue else {
                return
            }

            let offsetY = value.cgPointValue.y
            // 下拉才执行
            if offsetY > 0 {
                return
            }
            //dlog("offsetY: \(offsetY)")
            let newOffsetY = -offsetY - 25
            var progress = abs(newOffsetY) / kMaxHeaderPanHeight
            progress = progress >= 1 ? 1 : progress
            // * 一个系数，免得动画太快
            animationView.currentProgress = progress * 0.4
            animationView.alpha = progress + 0.5
        default:
            break
        }
    }
}

@objcMembers class RefreshFooterAnimator: MJRefreshAutoFooter {
    var noMoreData: String = ""

    private lazy var animationView: LottieAnimationView = {
        let animation = LottieAnimation.named("single_ring")
        let animationView = LottieAnimationView(animation: animation)
        
        animationView.contentMode = .scaleAspectFit
        animationView.loopMode = .loop
        animationView.backgroundBehavior = .pauseAndRestore
        animationView.size = CGSize(width: 16, height: 16)
        animationView.backgroundColor = .clear
        addSubview(animationView)
        return animationView
    }()

    private var noMoreDataCustomView = UIView() {
        didSet {
            stateLabel.isHidden = true
            noMoreDataCustomView.isHidden = true
            addSubview(noMoreDataCustomView)
            sendSubviewToBack(noMoreDataCustomView)
        }
    }

    private lazy var stateLabel: UILabel = {
        let label = UILabel()
        label.textColor = .white
        label.font = .systemFont(ofSize: 14)//.popRegular(size: 12)
        label.isHidden = true
        label.textAlignment = .center
        label.text = " "
        addSubview(label)
        return label
    }()

    private let kMaxFooterPanHeight: CGFloat = 50

    override func prepare() {
        super.prepare()
        noMoreData = "No more data~"//R.string.localizable.no_more_data.localized()//"No more data~"
        
        mj_h = kMaxFooterPanHeight
    }

    override func placeSubviews() {
        super.placeSubviews()

        if animationView.mj_x == 0 {
            animationView.center = CGPoint(x: mj_w / 2, y: mj_h / 2)
            animationView.mj_y = 10
        }

        if stateLabel.mj_y == 0 {
            stateLabel.mj_x = 0
            stateLabel.mj_y = 15
            stateLabel.mj_w = mj_w
            stateLabel.mj_h = 20
        }
        noMoreDataCustomView.frame = bounds
        bringSubviewToFront(stateLabel)
    }

    override var state: MJRefreshState {
        willSet {
            guard state != newValue else {
                return
            }
        }
        didSet {
            noMoreDataCustomView.isHidden = true
            stateLabel.isHidden = true

            switch state {
            case .refreshing:
                DispatchQueue.main.async { [weak self] in
                    self?.animationView.currentProgress = 0
                    self?.animationView.isHidden = false
                    self?.animationView.alpha = 1
                    self?.animationView.play()
                }

            case .pulling:
                let generator = UIImpactFeedbackGenerator(style: .light)
                generator.prepare()
                generator.impactOccurred()

            case .noMoreData:
                stateLabel.isHidden = false
                stateLabel.text = noMoreData
                noMoreDataCustomView.isHidden = false
                animationView.alpha = 0
                animationView.stop()
            case .idle:
                animationView.alpha = 0
                animationView.stop()

            default:
                break
            }
        }
    }

    override func scrollViewContentSizeDidChange(_ change: [AnyHashable: Any]?) {
        super.scrollViewContentSizeDidChange(change)

        guard let scrollView = scrollView else { return }

        let contentHeight = scrollView.mj_contentH + ignoredScrollViewContentInsetBottom
        var scrollHeight: CGFloat = 0

        if #available(iOS 11.0, *) {
            scrollHeight = scrollView.mj_h - self.scrollViewOriginalInset.top - self.scrollViewOriginalInset.bottom + self.ignoredScrollViewContentInsetBottom

        } else {
            scrollHeight = scrollView.mj_h - scrollViewOriginalInset.top + ignoredScrollViewContentInsetBottom
        }
        mj_y = max(contentHeight, scrollHeight)
    }

    override func scrollViewContentOffsetDidChange(_ change: [AnyHashable: Any]?) {
        super.scrollViewContentOffsetDidChange(change)

        if animationView.isAnimationPlaying {
            return
        }

        switch state {
        case .idle, .pulling:
            guard let dic = change else {
                return
            }
            guard let value = dic[NSKeyValueChangeKey.newKey] as? NSValue else {
                return
            }

            let offsetY = value.cgPointValue.y
            let newValue = offsetY - 25 > 0 ? offsetY - 25 : 0
            var progress = abs(newValue) / kMaxFooterPanHeight
            progress = progress >= 1 ? 1 : progress
            //dlog(progress)
            // * 一个系数，免得动画太快
            animationView.currentProgress = progress * 0.4
            animationView.alpha = progress + 0.5

        default:
            break
        }
    }

    override func scrollViewPanStateDidChange(_ change: [AnyHashable: Any]?) {
        super.scrollViewPanStateDidChange(change)
        if state != .refreshing {
            animationView.stop()
        }
    }
}

@objcMembers class RefreshTrailerAnimator: MJRefreshStateTrailer {
    private lazy var animationView: LottieAnimationView = {
        
        let animation = LottieAnimation.named("single_ring")
        let animationView = LottieAnimationView(animation: animation)
        
        animationView.contentMode = .scaleAspectFit
        animationView.loopMode = .loop
        animationView.backgroundBehavior = .pauseAndRestore
        animationView.size = CGSize(width: 100, height: 100)
        animationView.backgroundColor = .clear
        addSubview(animationView)
        return animationView
    }()

    
    override func placeSubviews() {
        super.placeSubviews()
        stateLabel?.isHidden = true
        
        self.mj_w = 70
        let selfCenter = CGPoint(x: self.mj_w / 2, y: self.mj_h / 2)
        animationView.center = selfCenter
    }
    
    override var state: MJRefreshState {
        willSet {
            guard state != newValue else {
                return
            }
        }
        didSet {
            super.state = state
            
            switch state {
            case .refreshing:
                DispatchQueue.main.async { [weak self] in
                    self?.animationView.play()
                }

            case .pulling:
                animationView.currentProgress = 0
                animationView.alpha = 1
                let generator = UIImpactFeedbackGenerator(style: .medium)
                generator.prepare()
                generator.impactOccurred()

            case .noMoreData:
                animationView.currentProgress = 0
                animationView.alpha = 0
                animationView.stop()
                
            default:
                break
            }
        }
    }
}



