<commit_before>//
//  NavigationBar.swift
//  AxReminder
//
//  Created by devedbox on 2017/6/26.
//  Copyright © 2017年 devedbox. All rights reserved.
//

import UIKit
import pop

private let DefaultTitleFontSize: CGFloat = 36.0
private let DefaultTitleUnselectedFontSize: CGFloat = 16.0
private let DefaultTabNavigationItemFontSize: CGFloat = 14.0
private let DefaultTabNavigationTitleItemPadding: CGFloat = 15.0
private let DefaultTabNavigationItemEdgeMargin: CGFloat = 8.0
private let DefaultTabNavigationItemHeight: CGFloat = 44.0
private let DefaultTabNavigationItemWidthThreshold: CGFloat = 30.0

private class _TabNavigationItemButton: UIButton { /* Custom view hooks. */ }
private class _TabNavigationTitleItemButton: UIButton { // Custom view hooks.
    weak var _titleItem: TabNavigationTitleItem?
}

private class _TabNavigationBarScrollViewHooks: NSObject {
    fileprivate var _completion: (()->Void)
    
    init(_ completion: @escaping ()->Void) {
        _completion = completion
        super.init()
    }
}

private class _TabNavigationItemView: UIView {
    var title: String? {
        didSet {
            _button.setTitle(title, for: .normal)
        }
    }
    var image: UIImage? {
        didSet {
            _button.setImage(image, for: .normal)
        }
    }
    
    
    // Button item.
    lazy var _button: _TabNavigationItemButton = { () -> _TabNavigationItemButton in
        let button = _TabNavigationItemButton(type: .system)
        button.translatesAutoresizingMaskIntoConstraints = false
        button.backgroundColor = UIColor.clear
        button.titleLabel?.font = UIFont(name: "PingFangSC-Semibold", size: DefaultTabNavigationItemFontSize)
        return button
    }()
    
    // Initialzier:
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        _initializer()
    }
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        
        _initializer()
    }
    
    private func _initializer() {
        translatesAutoresizingMaskIntoConstraints = false
        backgroundColor = .clear
        // Set up button.
        _setupButton()
    }
    
    // Private:
    private func _setupButton() {
        heightAnchor.constraint(equalToConstant: DefaultTabNavigationItemHeight).isActive = true
        widthAnchor.constraint(greaterThanOrEqualToConstant: DefaultTabNavigationItemWidthThreshold).isActive = true
        
        addSubview(_button)
        addConstraint(NSLayoutConstraint(item: self, attribute: .centerX, relatedBy: .equal, toItem: _button, attribute: .centerX, multiplier: 1.0, constant: 0.0))
        addConstraint(NSLayoutConstraint(item: self, attribute: .centerY, relatedBy: .equal, toItem: _button, attribute: .centerY, multiplier: 1.0, constant: 0.0))
        addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-(==6)-[_button]-(==6)-|", options: [], metrics: nil, views: ["_button":_button]))
        addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-(>=0)-[_button]-(>=0)-|", options: [], metrics: nil, views: ["_button":_button]))
    }
}

public class TabNavigationItem: NSObject {
    // MARK: - Properties.
    public var image: UIImage? {
        return _view.image
    }
    
    public var title: String? {
        return _view.title
    }
    
    public var tintColor: UIColor? {
        set { _view._button.tintColor = newValue }
        get { return _view._button.tintColor }
    }
    
    public var target: Any? {
        return _view._button.allTargets.first
    }
    
    public var selector: Selector? {
        guard let _selector = _view._button.actions(forTarget: target, forControlEvent: .touchUpInside)?.first else {
            return nil
        }
        return Selector(_selector)
    }
    
    internal var underlyingView: UIView { return _view }
    fileprivate var _view: _TabNavigationItemView = _TabNavigationItemView()
    
    public init(title: String?) {
        super.init()
        _view.title = title
    }
    
    public convenience init(image: UIImage? = nil, target: Any? = nil, selector: Selector? = nil) {
        self.init(title: nil)
        _view.image = image
        if selector != nil {
            _view._button.addTarget(target, action: selector!, for: .touchUpInside)
        }
    }
    
    public convenience init(title: String? = nil, target: Any? = nil, selector: Selector? = nil) {
        self.init(title: title)
        _view.title = title
        if selector != nil {
            _view._button.addTarget(target, action: selector!, for: .touchUpInside)
        }
    }
}

private class _TabNavigationBackItem: TabNavigationItem { /* Back navigation item*/ }

public class TabNavigationTitleItem: NSObject {
    public var selected: Bool {
        didSet {
            setSelected(selected, animated: false)
        }
    }
    
    public var selectedRange: Range<Int>? {
        didSet {
            if let _ = selectedRange {
                let attributedTitle = NSMutableAttributedString(string: _button.title(for: .normal)!, attributes: [NSFontAttributeName: titleFont(whenSelected: false), NSForegroundColorAttributeName: titleColor(whenSelected: false)])
                self._button.setAttributedTitle(attributedTitle, for: .normal)
            } else {
                self._button.setAttributedTitle(nil, for: .normal)
            }
        }
    }
    
    public var currentTitleColor: UIColor {
        return _selectionTitleColors[selected]!
    }
    
    public var currentTitleFont: UIFont {
        return _selectionTitleFonts[selected]!
    }
    
    private var _selectionTitleColors: [Bool: UIColor] = [true: UIColor(hex: "4A4A4A"), false: UIColor(hex: "CCCCCC")]
    private var _selectionTitleFonts: [Bool: UIFont] = [true: UIFont(name: "PingFangSC-Semibold", size: DefaultTitleFontSize)!, false: UIFont(name: "PingFangSC-Semibold", size: DefaultTitleUnselectedFontSize)!]
    
    public func setTitleColor(_ titleColor: UIColor, whenSelected selected: Bool) {
        _selectionTitleColors[selected] = titleColor
    }
    public func titleColor(whenSelected selected: Bool) -> UIColor {
        return _selectionTitleColors[selected]!
    }
    
    public func setTitleFont(_ titleFont: UIFont, whenSelected selected: Bool) {
        _selectionTitleFonts[selected] = titleFont
        if _selectionTitleFonts[true]!.fontName != _selectionTitleFonts[false]!.fontName {
            fatalError("Font for selected state and font for unselected state must have the same font family and name.")
        }
    }
    public func titleFont(whenSelected selected: Bool) -> UIFont {
        return _selectionTitleFonts[selected]!
    }
    
    public func setSelected(_ selected: Bool, animated: Bool, completion: (() -> Void)? = nil) {
        if animated {
            if let range = selectedRange {
                let _ns_range = NSMakeRange(range.lowerBound, range.upperBound - range.lowerBound)
                
                let _fontSizeAnimation = POPSpringAnimation()
                _fontSizeAnimation.property = POPAnimatableProperty.attributedButtonFontSize(named: _selectionTitleFonts[selected]!.fontName, range: _ns_range, state: .normal)
                _fontSizeAnimation.toValue = titleFont(whenSelected: selected).pointSize
                _fontSizeAnimation.removedOnCompletion = true
                self._button.pop_add(_fontSizeAnimation, forKey: "ATTRIBUTEDFONT")
                
                let _titleColorAnimation = POPSpringAnimation()
                _titleColorAnimation.property = POPAnimatableProperty.attributedButtonTextColor(for: _ns_range, state: .normal)
                _titleColorAnimation.toValue = _selectionTitleColors[selected]
                _titleColorAnimation.removedOnCompletion = true
                _titleColorAnimation.completionBlock = { animation, finished in
                    completion?()
                }
                self._button.pop_add(_titleColorAnimation, forKey: "ATTRIBUTEDCOLOR")
            } else {
                let _fontSizeAnimation = POPSpringAnimation()
                _fontSizeAnimation.property = POPAnimatableProperty.labelFontSize(named: _selectionTitleFonts[selected]!.fontName)
                _fontSizeAnimation.toValue = selected ? DefaultTitleFontSize : DefaultTitleUnselectedFontSize
                _fontSizeAnimation.removedOnCompletion = true
                self._button.titleLabel?.pop_add(_fontSizeAnimation, forKey: "FONT")
                
                let _titleColorAnimation = POPSpringAnimation()
                _titleColorAnimation.property = POPAnimatableProperty.buttonTitleColor(for: . normal)
                _titleColorAnimation.toValue = _selectionTitleColors[selected]
                _titleColorAnimation.removedOnCompletion = true
                self._button.pop_add(_titleColorAnimation, forKey: "COLOR")
                
                let _tintColorAnimation = POPSpringAnimation(propertyNamed: kPOPViewTintColor)
                _tintColorAnimation?.toValue = _selectionTitleColors[selected]
                _tintColorAnimation?.removedOnCompletion = true
                _tintColorAnimation?.completionBlock = { animation, finished in
                    completion?()
                }
                self._button.pop_add(_tintColorAnimation, forKey: "TINTCOLOR")
            }
        } else {
            if let range = selectedRange {
                let attributedTitle = NSMutableAttributedString(attributedString: self._button.attributedTitle(for: .normal)!)
                let _ns_range = NSMakeRange(range.lowerBound, range.upperBound - range.lowerBound)
                attributedTitle.addAttributes([NSFontAttributeName: titleFont(whenSelected: selected), NSForegroundColorAttributeName: titleColor(whenSelected: selected)], range: _ns_range)
                self._button.setAttributedTitle(attributedTitle, for: .normal)
            } else {
                self._button.titleLabel?.font = _selectionTitleFonts[selected]
                self._button.tintColor = _selectionTitleColors[selected]
                self._button.setTitleColor(_selectionTitleColors[selected], for: .normal)
            }
        }
    }
    
    fileprivate lazy var _button: _TabNavigationTitleItemButton = { () -> _TabNavigationTitleItemButton in
        let button = _TabNavigationTitleItemButton(type: .custom)
        button.titleLabel?.numberOfLines = 1
        button.adjustsImageWhenHighlighted = false
        return button
    }()
    
    public init(title: String) {
        selected = false
        super.init()
        _button.setTitle(title, for: .normal)
        _button._titleItem = self
    }
    
    public convenience init(title: String, selectedRange: Range<Int>? = nil) {
        self.init(title: title)
        self.selectedRange = selectedRange
    }
}

public class TabNavigationTitleActionItem: TabNavigationTitleItem {
    public override func setSelected(_ selected: Bool, animated: Bool, completion: (() -> Void)? = nil) {
        super.setSelected(false, animated: false, completion: completion)
    }
    
    public override func titleFont(whenSelected selected: Bool) -> UIFont {
        return super.titleFont(whenSelected: false)<commit_msg>Replaced with CountableRange.<commit_after>//
//  NavigationBar.swift
//  AxReminder
//
//  Created by devedbox on 2017/6/26.
//  Copyright © 2017年 devedbox. All rights reserved.
//

import UIKit
import pop

private let DefaultTitleFontSize: CGFloat = 36.0
private let DefaultTitleUnselectedFontSize: CGFloat = 16.0
private let DefaultTabNavigationItemFontSize: CGFloat = 14.0
private let DefaultTabNavigationTitleItemPadding: CGFloat = 15.0
private let DefaultTabNavigationItemEdgeMargin: CGFloat = 8.0
private let DefaultTabNavigationItemHeight: CGFloat = 44.0
private let DefaultTabNavigationItemWidthThreshold: CGFloat = 30.0

private class _TabNavigationItemButton: UIButton { /* Custom view hooks. */ }
private class _TabNavigationTitleItemButton: UIButton { // Custom view hooks.
    weak var _titleItem: TabNavigationTitleItem?
}

private class _TabNavigationBarScrollViewHooks: NSObject {
    fileprivate var _completion: (()->Void)
    
    init(_ completion: @escaping ()->Void) {
        _completion = completion
        super.init()
    }
}

private class _TabNavigationItemView: UIView {
    var title: String? {
        didSet {
            _button.setTitle(title, for: .normal)
        }
    }
    var image: UIImage? {
        didSet {
            _button.setImage(image, for: .normal)
        }
    }
    
    
    // Button item.
    lazy var _button: _TabNavigationItemButton = { () -> _TabNavigationItemButton in
        let button = _TabNavigationItemButton(type: .system)
        button.translatesAutoresizingMaskIntoConstraints = false
        button.backgroundColor = UIColor.clear
        button.titleLabel?.font = UIFont(name: "PingFangSC-Semibold", size: DefaultTabNavigationItemFontSize)
        return button
    }()
    
    // Initialzier:
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        _initializer()
    }
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        
        _initializer()
    }
    
    private func _initializer() {
        translatesAutoresizingMaskIntoConstraints = false
        backgroundColor = .clear
        // Set up button.
        _setupButton()
    }
    
    // Private:
    private func _setupButton() {
        heightAnchor.constraint(equalToConstant: DefaultTabNavigationItemHeight).isActive = true
        widthAnchor.constraint(greaterThanOrEqualToConstant: DefaultTabNavigationItemWidthThreshold).isActive = true
        
        addSubview(_button)
        addConstraint(NSLayoutConstraint(item: self, attribute: .centerX, relatedBy: .equal, toItem: _button, attribute: .centerX, multiplier: 1.0, constant: 0.0))
        addConstraint(NSLayoutConstraint(item: self, attribute: .centerY, relatedBy: .equal, toItem: _button, attribute: .centerY, multiplier: 1.0, constant: 0.0))
        addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-(==6)-[_button]-(==6)-|", options: [], metrics: nil, views: ["_button":_button]))
        addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-(>=0)-[_button]-(>=0)-|", options: [], metrics: nil, views: ["_button":_button]))
    }
}

public class TabNavigationItem: NSObject {
    // MARK: - Properties.
    public var image: UIImage? {
        return _view.image
    }
    
    public var title: String? {
        return _view.title
    }
    
    public var tintColor: UIColor? {
        set { _view._button.tintColor = newValue }
        get { return _view._button.tintColor }
    }
    
    public var target: Any? {
        return _view._button.allTargets.first
    }
    
    public var selector: Selector? {
        guard let _selector = _view._button.actions(forTarget: target, forControlEvent: .touchUpInside)?.first else {
            return nil
        }
        return Selector(_selector)
    }
    
    internal var underlyingView: UIView { return _view }
    fileprivate var _view: _TabNavigationItemView = _TabNavigationItemView()
    
    public init(title: String?) {
        super.init()
        _view.title = title
    }
    
    public convenience init(image: UIImage? = nil, target: Any? = nil, selector: Selector? = nil) {
        self.init(title: nil)
        _view.image = image
        if selector != nil {
            _view._button.addTarget(target, action: selector!, for: .touchUpInside)
        }
    }
    
    public convenience init(title: String? = nil, target: Any? = nil, selector: Selector? = nil) {
        self.init(title: title)
        _view.title = title
        if selector != nil {
            _view._button.addTarget(target, action: selector!, for: .touchUpInside)
        }
    }
}

private class _TabNavigationBackItem: TabNavigationItem { /* Back navigation item*/ }

public class TabNavigationTitleItem: NSObject {
    public var selected: Bool {
        didSet {
            setSelected(selected, animated: false)
        }
    }
    
    public var selectedRange: CountableRange<Int>? {
        didSet {
            if let _ = selectedRange {
                let attributedTitle = NSMutableAttributedString(string: _button.title(for: .normal)!, attributes: [NSFontAttributeName: titleFont(whenSelected: false), NSForegroundColorAttributeName: titleColor(whenSelected: false)])
                self._button.setAttributedTitle(attributedTitle, for: .normal)
            } else {
                self._button.setAttributedTitle(nil, for: .normal)
            }
        }
    }
    
    public var currentTitleColor: UIColor {
        return _selectionTitleColors[selected]!
    }
    
    public var currentTitleFont: UIFont {
        return _selectionTitleFonts[selected]!
    }
    
    private var _selectionTitleColors: [Bool: UIColor] = [true: UIColor(hex: "4A4A4A"), false: UIColor(hex: "CCCCCC")]
    private var _selectionTitleFonts: [Bool: UIFont] = [true: UIFont(name: "PingFangSC-Semibold", size: DefaultTitleFontSize)!, false: UIFont(name: "PingFangSC-Semibold", size: DefaultTitleUnselectedFontSize)!]
    
    public func setTitleColor(_ titleColor: UIColor, whenSelected selected: Bool) {
        _selectionTitleColors[selected] = titleColor
    }
    public func titleColor(whenSelected selected: Bool) -> UIColor {
        return _selectionTitleColors[selected]!
    }
    
    public func setTitleFont(_ titleFont: UIFont, whenSelected selected: Bool) {
        _selectionTitleFonts[selected] = titleFont
        if _selectionTitleFonts[true]!.fontName != _selectionTitleFonts[false]!.fontName {
            fatalError("Font for selected state and font for unselected state must have the same font family and name.")
        }
    }
    public func titleFont(whenSelected selected: Bool) -> UIFont {
        return _selectionTitleFonts[selected]!
    }
    
    public func setSelected(_ selected: Bool, animated: Bool, completion: (() -> Void)? = nil) {
        if animated {
            if let range = selectedRange {
                let _ns_range = NSMakeRange(range.lowerBound, range.upperBound - range.lowerBound)
                
                let _fontSizeAnimation = POPSpringAnimation()
                _fontSizeAnimation.property = POPAnimatableProperty.attributedButtonFontSize(named: _selectionTitleFonts[selected]!.fontName, range: _ns_range, state: .normal)
                _fontSizeAnimation.toValue = titleFont(whenSelected: selected).pointSize
                _fontSizeAnimation.removedOnCompletion = true
                self._button.pop_add(_fontSizeAnimation, forKey: "ATTRIBUTEDFONT")
                
                let _titleColorAnimation = POPSpringAnimation()
                _titleColorAnimation.property = POPAnimatableProperty.attributedButtonTextColor(for: _ns_range, state: .normal)
                _titleColorAnimation.toValue = _selectionTitleColors[selected]
                _titleColorAnimation.removedOnCompletion = true
                _titleColorAnimation.completionBlock = { animation, finished in
                    completion?()
                }
                self._button.pop_add(_titleColorAnimation, forKey: "ATTRIBUTEDCOLOR")
            } else {
                let _fontSizeAnimation = POPSpringAnimation()
                _fontSizeAnimation.property = POPAnimatableProperty.labelFontSize(named: _selectionTitleFonts[selected]!.fontName)
                _fontSizeAnimation.toValue = selected ? DefaultTitleFontSize : DefaultTitleUnselectedFontSize
                _fontSizeAnimation.removedOnCompletion = true
                self._button.titleLabel?.pop_add(_fontSizeAnimation, forKey: "FONT")
                
                let _titleColorAnimation = POPSpringAnimation()
                _titleColorAnimation.property = POPAnimatableProperty.buttonTitleColor(for: . normal)
                _titleColorAnimation.toValue = _selectionTitleColors[selected]
                _titleColorAnimation.removedOnCompletion = true
                self._button.pop_add(_titleColorAnimation, forKey: "COLOR")
                
                let _tintColorAnimation = POPSpringAnimation(propertyNamed: kPOPViewTintColor)
                _tintColorAnimation?.toValue = _selectionTitleColors[selected]
                _tintColorAnimation?.removedOnCompletion = true
                _tintColorAnimation?.completionBlock = { animation, finished in
                    completion?()
                }
                self._button.pop_add(_tintColorAnimation, forKey: "TINTCOLOR")
            }
        } else {
            if let range = selectedRange {
                let attributedTitle = NSMutableAttributedString(attributedString: self._button.attributedTitle(for: .normal)!)
                let _ns_range = NSMakeRange(range.lowerBound, range.upperBound - range.lowerBound)
                attributedTitle.addAttributes([NSFontAttributeName: titleFont(whenSelected: selected), NSForegroundColorAttributeName: titleColor(whenSelected: selected)], range: _ns_range)
                self._button.setAttributedTitle(attributedTitle, for: .normal)
            } else {
                self._button.titleLabel?.font = _selectionTitleFonts[selected]
                self._button.tintColor = _selectionTitleColors[selected]
                self._button.setTitleColor(_selectionTitleColors[selected], for: .normal)
            }
        }
    }
    
    fileprivate lazy var _button: _TabNavigationTitleItemButton = { () -> _TabNavigationTitleItemButton in
        let button = _TabNavigationTitleItemButton(type: .custom)
        button.titleLabel?.numberOfLines = 1
        button.adjustsImageWhenHighlighted = false
        return button
    }()
    
    public init(title: String) {
        selected = false
        super.init()
        _button.setTitle(title, for: .normal)
        _button._titleItem = self
    }
    
    public convenience init(title: String, selectedRange: CountableRange<Int>? = nil) {
        self.init(title: title)
        self.selectedRange = selectedRange
    }
}

public class TabNavigationTitleActionItem: TabNavigationTitleItem {
    public override func setSelected(_ selected: Bool, animated: Bool, completion: (() -> Void)? = nil) {
        super.setSelected(false, animated: false, completion: completion)
    }
    
    public override func titleFont(whenSelected selected: Bool) -> UIFont {
        return super.titleFont(whenSelected: false)
{'fraction_non_alphanumeric': 0.08866536689117334, 'fraction_numerical': 0.004165189649060617, 'mean_word_length': 2.7071287779237845, 'pattern_counts': {'":': 4, '<': 7, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2764980', 'n_tokens_mistral': 6239, 'n_tokens_neox': 6028, 'n_words': 1333}