--- /dev/null
+//
+// FilterViewController.swift
+// WolneLektury
+//
+// Created by Pawel Dabrowski on 30/05/2018.
+// Copyright © 2018 Fundacja Nowoczesna Polska. All rights reserved.
+//
+
+import UIKit
+import Toast_Swift
+
+enum FilterSection: Int{
+ case onlyLectures = 0
+ case hasAudiobook
+ case epochs
+ case kinds
+ case genres
+
+ var title: String{
+ return "filter_\(self)".localized.uppercased()
+ }
+
+ var failedText: String{
+ return "load_\(self)_failed".localized
+ }
+}
+
+class LeftAlignedCollectionViewFlowLayout: UICollectionViewFlowLayout {
+
+ override init() {
+ super.init()
+ minimumLineSpacing = 0
+
+ }
+
+ required init?(coder aDecoder: NSCoder) {
+ fatalError("init(coder:) has not been implemented")
+ }
+
+ override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
+ let attributes = super.layoutAttributesForElements(in: rect)
+
+ var leftMargin = sectionInset.left
+ var maxY: CGFloat = -1.0
+ attributes?.forEach { layoutAttribute in
+
+ if(layoutAttribute.representedElementCategory == .cell){
+ if layoutAttribute.frame.origin.y >= maxY {
+ leftMargin = sectionInset.left
+ }
+
+ layoutAttribute.frame.origin.x = leftMargin
+
+ leftMargin += layoutAttribute.frame.width + minimumInteritemSpacing
+ maxY = max(layoutAttribute.frame.maxY , maxY)
+ }
+ }
+ return attributes
+ }
+}
+
+protocol FilterViewControllerDelegate: class {
+ func filterViewControllerDidSelectItems(kindsArray: [CategoryModel], epochsArray: [CategoryModel], genresArray: [CategoryModel], onlyLectures: Bool, hasAudiobook: Bool, filterChanged: Bool)
+}
+
+class FilterViewController: WLViewController {
+
+ class func instance(delegate: FilterViewControllerDelegate, selectedKindsArray: [CategoryModel], selectedEpochsArray: [CategoryModel], selectedGenresArray: [CategoryModel], onlyLectures: Bool, hasAudiobook: Bool) -> FilterViewController{
+ let controller = FilterViewController.instance()
+ controller.initialSelectedKindsArray = selectedKindsArray
+ controller.initialSelectedEpochsArray = selectedEpochsArray
+ controller.initialSelectedGenresArray = selectedGenresArray
+ controller.onlyLectures = onlyLectures
+ controller.hasAudiobook = hasAudiobook
+ controller.delegate = delegate
+ return controller
+ }
+
+ weak var delegate: FilterViewControllerDelegate!
+ @IBOutlet weak var collectionView: UICollectionView!
+
+ var initialSelectedKindsArray: [CategoryModel]!
+ var initialSelectedEpochsArray: [CategoryModel]!
+ var initialSelectedGenresArray: [CategoryModel]!
+
+ var kindsArray: [CategoryModel]?
+ var epochsArray: [CategoryModel]?
+ var genresArray: [CategoryModel]?
+
+ var kindsSection: FilterSectionHeaderCollectionReusableView?
+ var epochsSection: FilterSectionHeaderCollectionReusableView?
+ var genresSection: FilterSectionHeaderCollectionReusableView?
+
+ var isKindsDownloading = false
+ var isEpochsDownloading = false
+ var isGenresDownloading = false
+
+ var filterChanged = false
+ var onlyLectures = false
+ var hasAudiobook = false
+
+ override func viewDidLoad() {
+ super.viewDidLoad()
+
+ title = "filters".localized
+
+ setupCollectionView()
+
+ getData(filterSection: .epochs)
+ getData(filterSection: .kinds)
+ getData(filterSection: .genres)
+ }
+
+ @IBAction func closeAction(_ sender: Any) {
+ navigationController?.dismiss(animated: true, completion: nil)
+ }
+
+ @IBAction func confirmAction(_ sender: Any) {
+ delegate.filterViewControllerDidSelectItems(kindsArray: kindsArray?.filter({$0.checked == true}) ?? [CategoryModel](), epochsArray: epochsArray?.filter({$0.checked == true}) ?? [CategoryModel](), genresArray: genresArray?.filter({$0.checked == true}) ?? [CategoryModel](), onlyLectures: onlyLectures, hasAudiobook: hasAudiobook, filterChanged: filterChanged)
+ }
+
+ func getSection(filterSection: FilterSection) -> FilterSectionHeaderCollectionReusableView? {
+ switch filterSection {
+ case .epochs:
+ return epochsSection
+ case .genres:
+ return genresSection
+ case .kinds:
+ return kindsSection
+ default:
+ return nil
+ }
+ }
+
+ func setDataSource(filterSection:FilterSection, dSource: [CategoryModel]?) {
+ switch filterSection {
+ case .epochs:
+ if let arr = dSource{
+ for obj in initialSelectedEpochsArray{
+ arr.first(where: {$0.slug == obj.slug})?.checked = true
+ }
+ }
+ epochsArray = dSource
+ case .genres:
+ if let arr = dSource{
+ for obj in initialSelectedGenresArray{
+ arr.first(where: {$0.slug == obj.slug})?.checked = true
+ }
+ }
+ genresArray = dSource
+ case .kinds:
+ if let arr = dSource{
+ for obj in initialSelectedKindsArray{
+ arr.first(where: {$0.slug == obj.slug})?.checked = true
+ }
+ }
+ kindsArray = dSource
+ default:
+ break
+ }
+ }
+
+ func setIsDownloading(isDownloading: Bool, section: FilterSection){
+ switch section {
+ case .epochs:
+ isEpochsDownloading = isDownloading
+ case .genres:
+ isGenresDownloading = isDownloading
+ case .kinds:
+ isKindsDownloading = isDownloading
+ default:
+ break
+ }
+ }
+
+ func getIsDownloading(section: FilterSection) -> Bool{
+ switch section {
+ case .epochs:
+ return isEpochsDownloading
+ case .genres:
+ return isGenresDownloading
+ case .kinds:
+ return isKindsDownloading
+ default:
+ return false
+ }
+ }
+
+ func getData(filterSection: FilterSection){
+
+ getSection(filterSection: filterSection)?.refreshButton.setIndicatorButtonState(state: .loading)
+ setIsDownloading(isDownloading: true, section: filterSection)
+
+ syncManager.getCategories(filterSection: filterSection, bookOnly: true) { [weak self] (result) in
+ self?.setIsDownloading(isDownloading: false, section: filterSection)
+ switch result {
+ case .success(let model):
+ self?.getSection(filterSection: filterSection)?.refreshButton.setIndicatorButtonState(state: .hidden)
+ self?.setDataSource(filterSection: filterSection, dSource: model as? [CategoryModel])
+ self?.collectionView.reloadSections([filterSection.rawValue])
+ case .failure/*(let *error)*/:
+ self?.getSection(filterSection: filterSection)?.refreshButton.setIndicatorButtonState(state: .button)
+ self?.view.makeToast(filterSection.failedText, duration: 3.0, position: .bottom)
+ }
+ }
+ }
+
+ func setupCollectionView(){
+
+ collectionView.backgroundColor = UIColor.clear
+ collectionView.delegate = self
+ collectionView.dataSource = self
+ collectionView.register(UINib.init(nibName: "FilterCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "FilterCollectionViewCell")
+ collectionView.register(UINib.init(nibName: "FilterSectionHeaderCollectionReusableView", bundle: nil), forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "FilterSectionHeaderCollectionReusableView")
+ collectionView.register(UINib.init(nibName: "FilterOnlyLecturesReusableView", bundle: nil), forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "FilterOnlyLecturesReusableView")
+
+ if #available(iOS 11.0, *) {
+ collectionView.contentInsetAdjustmentBehavior = .always
+ }
+
+ collectionView.setCollectionViewLayout(LeftAlignedCollectionViewFlowLayout(), animated: true)
+ }
+
+ func getArrayForSection(filterSection: FilterSection) -> [CategoryModel]?{
+ switch filterSection{
+ case .onlyLectures, .hasAudiobook:
+ return nil
+ case .epochs:
+ return epochsArray
+ case .genres:
+ return genresArray
+ case .kinds:
+ return kindsArray
+ }
+ }
+
+ func numberOfRowsInSection(filterSection: FilterSection) -> Int{
+ return getArrayForSection(filterSection: filterSection)?.count ?? 0
+ }
+
+ func clearSectionHeaderReference(section: FilterSectionHeaderCollectionReusableView) {
+ if genresSection == section{
+ genresSection = nil
+ }
+ if epochsSection == section{
+ epochsSection = nil
+ }
+ if kindsSection == section{
+ kindsSection = nil
+ }
+ }
+}
+
+extension FilterViewController: UICollectionViewDelegateFlowLayout{
+
+ func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
+
+ if let items = getArrayForSection(filterSection: FilterSection(rawValue: indexPath.section)!){
+ let item = items[indexPath.row]
+ return CGSize(width: item.name.uppercased().width(withConstrainedHeight: 20, font: UIFont.systemFont(ofSize: 14, weight: .medium)) + 40, height: 30)
+ }
+ return CGSize(width: 50, height: 30)
+ }
+
+ func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
+
+ if indexPath.section == 0{
+ let sectionHeader = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "FilterOnlyLecturesReusableView", for: indexPath) as? FilterOnlyLecturesReusableView
+ sectionHeader?.delegate = self
+ sectionHeader?.onSwitch.isOn = onlyLectures
+ sectionHeader?.setup(isAudiobook: false)
+ return sectionHeader!
+ }
+ if indexPath.section == 1{
+ let sectionHeader = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "FilterOnlyLecturesReusableView", for: indexPath) as? FilterOnlyLecturesReusableView
+ sectionHeader?.delegate = self
+ sectionHeader?.onSwitch.isOn = hasAudiobook
+ sectionHeader?.setup(isAudiobook: true)
+ return sectionHeader!
+ }
+
+ else{
+ let sectionHeader = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "FilterSectionHeaderCollectionReusableView", for: indexPath) as! FilterSectionHeaderCollectionReusableView
+ clearSectionHeaderReference(section: sectionHeader)
+
+ let filterSection = FilterSection(rawValue: indexPath.section)!
+ sectionHeader.setup(filterSection: filterSection, isDownloading: getIsDownloading(section: filterSection))
+ sectionHeader.delegate = self
+
+ if indexPath.section == FilterSection.epochs.rawValue{
+ epochsSection = sectionHeader
+ }
+ else if indexPath.section == FilterSection.genres.rawValue{
+ genresSection = sectionHeader
+ }
+ else if indexPath.section == FilterSection.kinds.rawValue{
+ kindsSection = sectionHeader
+ }
+ return sectionHeader
+ }
+ }
+
+ func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
+
+ if section == 0 || section == 1{
+ return CGSize(width: UIScreen.main.bounds.width, height: 44)
+ }
+ else{
+ if getArrayForSection(filterSection: FilterSection(rawValue: section)!) != nil{
+ return CGSize(width: UIScreen.main.bounds.width, height: 44)
+ }
+ else{
+ return CGSize(width: UIScreen.main.bounds.width, height: 180)
+ }
+ }
+ }
+}
+
+extension FilterViewController: UICollectionViewDataSource{ //UICollectionViewDataSource
+
+ func numberOfSections(in collectionView: UICollectionView) -> Int {
+ return 5
+ }
+
+ func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int{
+ return numberOfRowsInSection(filterSection: FilterSection(rawValue: section)!)
+ }
+
+ func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell{
+
+ let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "FilterCollectionViewCell", for: indexPath) as! FilterCollectionViewCell
+
+ if let items = getArrayForSection(filterSection: FilterSection(rawValue: indexPath.section)!){
+ cell.setup(categoryModel: items[indexPath.row])
+ }
+ return cell
+ }
+}
+
+extension FilterViewController: UICollectionViewDelegate{
+ func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
+
+ if let items = getArrayForSection(filterSection: FilterSection(rawValue: indexPath.section)!), items.count > indexPath.row{
+ filterChanged = true
+ let item = items[indexPath.row]
+ item.checked = !item.checked
+ if let cell = collectionView.cellForItem(at: indexPath) as? FilterCollectionViewCell{
+ cell.setChecked(value: item.checked)
+ }
+ }
+ }
+}
+
+extension FilterViewController: FilterOnlyLecturesReusableViewDelegate{
+ func filterOnlyLecturesReusableViewSwitchValueChanged(value: Bool, isAudiobook: Bool){
+ if isAudiobook {
+ hasAudiobook = value
+ }
+ else {
+ onlyLectures = value
+ }
+ filterChanged = true
+ }
+}
+
+extension FilterViewController: FilterSectionHeaderCollectionReusableViewDelegate{
+ func filterSectionRefreshButtonTapped(section: FilterSection){
+ getData(filterSection: section)
+ }
+}