<commit_before>//
//  MasterTableViewSectionHeader.swift
//  NetNewsWire
//
//  Created by <NAME> on 4/18/19.
//  Copyright © 2019 Ranchero Software. All rights reserved.
//

import UIKit

class MasterFeedTableViewSectionHeader: UITableViewHeaderFooterView {
	
	override var accessibilityLabel: String? {
		set {}
		get {
			if unreadCount > 0 {
				let unreadLabel = NSLocalizedString("unread", comment: "Unread label for accessiblity")
				return "\(name) \(unreadCount) \(unreadLabel)"
			} else {
				return name
			}
		}
	}
	
	var unreadCount: Int {
		get {
			return unreadCountView.unreadCount
		}
		set {
			if unreadCountView.unreadCount != newValue {
				unreadCountView.unreadCount = newValue
				updateUnreadCountView()
				setNeedsLayout()
			}
		}
	}
	
	var name: String {
		get {
			return titleView.text ?? ""
		}
		set {
			if titleView.text != newValue {
				titleView.text = newValue
				setNeedsDisplay()
				setNeedsLayout()
			}
		}
	}
	
	var disclosureExpanded = false {
		didSet {
			updateExpandedState()
			updateUnreadCountView()
		}
	}
	
	var isLastSection = false
	
	private let titleView: UILabel = {
		let label = NonIntrinsicLabel()
		label.numberOfLines = 0
		label.allowsDefaultTighteningForTruncation = false
		label.adjustsFontForContentSizeCategory = true
		label.font = .preferredFont(forTextStyle: .body)
		return label
	}()
	
	private let unreadCountView = MasterFeedUnreadCountView(frame: CGRect.zero)
	private var disclosureView: UIImageView = {
		let iView = NonIntrinsicImageView()
		iView.tintColor = UIColor.tertiaryLabel
		iView.image = AppAssets.disclosureImage
		iView.contentMode = .center
		return iView
	}()

	private let topSeparatorView: UIView = {
		let view = UIView()
		view.backgroundColor = UIColor.separator
		return view
	}()
	
	private let bottomSeparatorView: UIView = {
		let view = UIView()
		view.backgroundColor = UIColor.separator
		return view
	}()
	
	override init(reuseIdentifier: String?) {
		super.init(reuseIdentifier: reuseIdentifier)
		commonInit()
	}
	
	required init?(coder: NSCoder) {
		super.init(coder: coder)
		commonInit()
	}
	
	override func sizeThatFits(_ size: CGSize) -> CGSize {
		
		let unreadCountView = MasterFeedUnreadCountView(frame: CGRect.zero)

		// Since we can't reload Section Headers to reset the height after we get the
		// unread count did change, we always assume a large unread count
		//
		// This means that sometimes on the second to largest font size will have extra
		// space under the account name.  This is better than having it overflow into the
		// cell below.
		unreadCountView.unreadCount = 888
		
		let layout = MasterFeedTableViewCellLayout(cellWidth: size.width, insets: safeAreaInsets, label: titleView, unreadCountView: unreadCountView, showingEditingControl: false, indent: false, shouldShowDisclosure: true)
		
		return CGSize(width: bounds.width, height: layout.height)
		
	}

	override func layoutSubviews() {
		super.layoutSubviews()
		let layout = MasterFeedTableViewCellLayout(cellWidth: bounds.size.width, insets: safeAreaInsets, label: titleView, unreadCountView: unreadCountView, showingEditingControl: false, indent: false, shouldShowDisclosure: true)
		layoutWith(layout)
	}

}

private extension MasterFeedTableViewSectionHeader {
	
	func commonInit() {
		addSubviewAtInit(unreadCountView)
		addSubviewAtInit(titleView)
		updateExpandedState()
		addSubviewAtInit(disclosureView)
		addBackgroundView()
		addSubviewAtInit(topSeparatorView)
		addSubviewAtInit(bottomSeparatorView)
	}
	
	func updateExpandedState() {
		if !isLastSection && self.disclosureExpanded {
			self.bottomSeparatorView.isHidden = false
		}
		UIView.animate(
			withDuration: 0.3,
			animations: {
				if self.disclosureExpanded {
					self.disclosureView.transform = CGAffineTransform(rotationAngle: 1.570796)
				} else {
					self.disclosureView.transform = CGAffineTransform(rotationAngle: 0)
				}
			}, completion: { _ in
				if !self.isLastSection && !self.disclosureExpanded {
					self.bottomSeparatorView.isHidden = true
				}
			})
	}
	
	func updateUnreadCountView() {
		if !disclosureExpanded && unreadCount > 0 {
			unreadCountView.isHidden = false
		} else {
			self.unreadCountView.isHidden = true
		}
	}

	func addSubviewAtInit(_ view: UIView) {
		addSubview(view)
		view.translatesAutoresizingMaskIntoConstraints = false
	}
	
	func layoutWith(_ layout: MasterFeedTableViewCellLayout) {
		titleView.setFrameIfNotEqual(layout.titleRect)
		unreadCountView.setFrameIfNotEqual(layout.unreadCountRect)
		disclosureView.setFrameIfNotEqual(layout.disclosureButtonRect)
		
		let top = CGRect(x: safeAreaInsets.left, y: 0, width: frame.width - safeAreaInsets.right - safeAreaInsets.left, height: 0.25)
		topSeparatorView.setFrameIfNotEqual(top)
		let bottom = CGRect(x: safeAreaInsets.left, y: frame.height - 0.25, width: frame.width - safeAreaInsets.right - safeAreaInsets.left, height: 0.25)
		bottomSeparatorView.setFrameIfNotEqual(bottom)
	}
	
	func addBackgroundView() {<commit_msg>Add fade in fade out animation for Account unread counts.  Issue #1228<commit_after>//
//  MasterTableViewSectionHeader.swift
//  NetNewsWire
//
//  Created by <NAME> on 4/18/19.
//  Copyright © 2019 Ranchero Software. All rights reserved.
//

import UIKit

class MasterFeedTableViewSectionHeader: UITableViewHeaderFooterView {
	
	override var accessibilityLabel: String? {
		set {}
		get {
			if unreadCount > 0 {
				let unreadLabel = NSLocalizedString("unread", comment: "Unread label for accessiblity")
				return "\(name) \(unreadCount) \(unreadLabel)"
			} else {
				return name
			}
		}
	}
	
	var unreadCount: Int {
		get {
			return unreadCountView.unreadCount
		}
		set {
			if unreadCountView.unreadCount != newValue {
				unreadCountView.unreadCount = newValue
				updateUnreadCountView()
				setNeedsLayout()
			}
		}
	}
	
	var name: String {
		get {
			return titleView.text ?? ""
		}
		set {
			if titleView.text != newValue {
				titleView.text = newValue
				setNeedsDisplay()
				setNeedsLayout()
			}
		}
	}
	
	var disclosureExpanded = false {
		didSet {
			updateExpandedState()
			updateUnreadCountView()
		}
	}
	
	var isLastSection = false
	
	private let titleView: UILabel = {
		let label = NonIntrinsicLabel()
		label.numberOfLines = 0
		label.allowsDefaultTighteningForTruncation = false
		label.adjustsFontForContentSizeCategory = true
		label.font = .preferredFont(forTextStyle: .body)
		return label
	}()
	
	private let unreadCountView = MasterFeedUnreadCountView(frame: CGRect.zero)
	private var disclosureView: UIImageView = {
		let iView = NonIntrinsicImageView()
		iView.tintColor = UIColor.tertiaryLabel
		iView.image = AppAssets.disclosureImage
		iView.contentMode = .center
		return iView
	}()

	private let topSeparatorView: UIView = {
		let view = UIView()
		view.backgroundColor = UIColor.separator
		return view
	}()
	
	private let bottomSeparatorView: UIView = {
		let view = UIView()
		view.backgroundColor = UIColor.separator
		return view
	}()
	
	override init(reuseIdentifier: String?) {
		super.init(reuseIdentifier: reuseIdentifier)
		commonInit()
	}
	
	required init?(coder: NSCoder) {
		super.init(coder: coder)
		commonInit()
	}
	
	override func sizeThatFits(_ size: CGSize) -> CGSize {
		
		let unreadCountView = MasterFeedUnreadCountView(frame: CGRect.zero)

		// Since we can't reload Section Headers to reset the height after we get the
		// unread count did change, we always assume a large unread count
		//
		// This means that sometimes on the second to largest font size will have extra
		// space under the account name.  This is better than having it overflow into the
		// cell below.
		unreadCountView.unreadCount = 888
		
		let layout = MasterFeedTableViewCellLayout(cellWidth: size.width, insets: safeAreaInsets, label: titleView, unreadCountView: unreadCountView, showingEditingControl: false, indent: false, shouldShowDisclosure: true)
		
		return CGSize(width: bounds.width, height: layout.height)
		
	}

	override func layoutSubviews() {
		super.layoutSubviews()
		let layout = MasterFeedTableViewCellLayout(cellWidth: bounds.size.width, insets: safeAreaInsets, label: titleView, unreadCountView: unreadCountView, showingEditingControl: false, indent: false, shouldShowDisclosure: true)
		layoutWith(layout)
	}

}

private extension MasterFeedTableViewSectionHeader {
	
	func commonInit() {
		addSubviewAtInit(unreadCountView)
		addSubviewAtInit(titleView)
		updateExpandedState()
		addSubviewAtInit(disclosureView)
		addBackgroundView()
		addSubviewAtInit(topSeparatorView)
		addSubviewAtInit(bottomSeparatorView)
	}
	
	func updateExpandedState() {
		if !isLastSection && self.disclosureExpanded {
			self.bottomSeparatorView.isHidden = false
		}
		UIView.animate(
			withDuration: 0.3,
			animations: {
				if self.disclosureExpanded {
					self.disclosureView.transform = CGAffineTransform(rotationAngle: 1.570796)
				} else {
					self.disclosureView.transform = CGAffineTransform(rotationAngle: 0)
				}
			}, completion: { _ in
				if !self.isLastSection && !self.disclosureExpanded {
					self.bottomSeparatorView.isHidden = true
				}
			})
	}
	
	func updateUnreadCountView() {
		if !disclosureExpanded && unreadCount > 0 {
			UIView.animate(withDuration: 0.3) {
				self.unreadCountView.alpha = 1
			}
		} else {
			UIView.animate(withDuration: 0.3) {
				self.unreadCountView.alpha = 0
			}
		}
	}

	func addSubviewAtInit(_ view: UIView) {
		addSubview(view)
		view.translatesAutoresizingMaskIntoConstraints = false
	}
	
	func layoutWith(_ layout: MasterFeedTableViewCellLayout) {
		titleView.setFrameIfNotEqual(layout.titleRect)
		unreadCountView.setFrameIfNotEqual(layout.unreadCountRect)
		disclosureView.setFrameIfNotEqual(layout.disclosureButtonRect)
		
		let top = CGRect(x: safeAreaInsets.left, y: 0, width: frame.width - safeAreaInsets.right - safeAreaInsets.left, height: 0.25)
		topSeparatorView.setFrameIfNotEqual(top)
		let bottom = CGRect(x: safeAreaInsets.left, y: frame.height - 0.25, width: frame.width - safeAreaInsets.right - safeAreaInsets.left, height: 0.25)
		bottomSeparatorView.setFrameIfNotEqual(bottom)
	}
	
	func addBackgroundView() {
{'fraction_non_alphanumeric': 0.09064010257421837, 'fraction_numerical': 0.007890324489594635, 'mean_word_length': 4.123799898938858, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 11, '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': '12186', 'n_tokens_mistral': 3735, 'n_tokens_neox': 3220, 'n_words': 727}