//
//  CycleBanner.swift
//  CycleBanner
//
//  Created by 王彦睿 on 2017/1/9.
//  Copyright © 2017年 家健文化传媒. All rights reserved.
//

import UIKit

open class CycleBanner: UIView {
    
    /// 图片自动滑动时间间隔
    public var duration: TimeInterval = 4.0
    
    /// page control 的位置
    public var dotLocation: CycleBannerPageDotLocation = .rightBottom
    
    /// 是否自动滑动
    public var autoScroll = true
    
    public var delegate: CycleBannerDelegate?
    
    public var dataSource: CycleBannerDataSource?
    
    /// 总的 cell 数量， 通常为图片数量 * 100
    fileprivate var totalItemCount = 0
    
    /// 自动滑动的计时器
    fileprivate var timer: Timer? = Timer()
    
    fileprivate var imageCollectionView: UICollectionView?
    
    fileprivate let flowLayout = UICollectionViewFlowLayout()
    
    /// 用于提醒用户图片未知的小圆点
    fileprivate var pageControl: UIPageControl?
    
    public override init(frame: CGRect) {
        super.init(frame: frame)
        setupUI()
    }
    
    required public init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }
    
    public convenience init(autoScroll: Bool = true) {
        self.init(frame: CGRect.zero)
        self.autoScroll = autoScroll
    }
    
    open override func layoutSubviews() {
        super.layoutSubviews()
        flowLayout.itemSize = frame.size
        totalItemCount = 100 * (dataSource?.numberOfImagesInCycleBanner())!
        let index = IndexPath(item: totalItemCount / 2, section: 0)
        imageCollectionView?.scrollToItem(at: index, at: [], animated: false)
        pageControl?.numberOfPages = (dataSource?.numberOfImagesInCycleBanner())!
    }
    
    public func refreshImageCollectionView() {
        imageCollectionView = UICollectionView(frame: bounds, collectionViewLayout: flowLayout)
    }
    
    fileprivate func setupUI() {
        translatesAutoresizingMaskIntoConstraints = false
        initImageCollectionView()
        initPageControl()
    }
    
    fileprivate func initImageCollectionView() {
        flowLayout.minimumLineSpacing = 0
        flowLayout.scrollDirection = .horizontal
        imageCollectionView = UICollectionView(frame: bounds, collectionViewLayout: flowLayout)
        imageCollectionView?.delegate = self
        imageCollectionView?.dataSource = self
        imageCollectionView?.isPagingEnabled = true
        imageCollectionView?.showsVerticalScrollIndicator = false
        imageCollectionView?.showsHorizontalScrollIndicator = false
        imageCollectionView?.scrollsToTop = false
        imageCollectionView?.translatesAutoresizingMaskIntoConstraints = false
        imageCollectionView?.register(CycleBannerCell.self, forCellWithReuseIdentifier: CycleBannerCellCommon.identifier)
        imageCollectionView?.backgroundColor = UIColor.clear
        addSubview(imageCollectionView!)
    }
    
    fileprivate func initPageControl() {
        pageControl = UIPageControl()
        pageControl?.currentPage = 0
        pageControl?.currentPageIndicatorTintColor = UIColor.black
        pageControl?.pageIndicatorTintColor = UIColor.white
        pageControl?.translatesAutoresizingMaskIntoConstraints = false
        addSubview(pageControl!)
    }
    
    fileprivate func makeConstraints() {
        if #available(iOS 9.0, *) {
            NSLayoutConstraint.activate([imageCollectionView!.topAnchor.constraint(equalTo: topAnchor),
                                         imageCollectionView!.bottomAnchor.constraint(equalTo: bottomAnchor),
                                         imageCollectionView!.leadingAnchor.constraint(equalTo: leadingAnchor),
                                         imageCollectionView!.trailingAnchor.constraint(equalTo: trailingAnchor)])
            var pageControlConstraints = [
                pageControl!.heightAnchor.constraint(equalToConstant: 20),
                pageControl!.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -5)]
            switch dotLocation {
            case .centerBottom:
                pageControlConstraints.append(pageControl!.centerXAnchor.constraint(equalTo: centerXAnchor))
            case .leftBottom:
                pageControlConstraints.append(pageControl!.leadingAnchor.constraint(greaterThanOrEqualTo: leadingAnchor, constant: 5))
            case .rightBottom:
                pageControlConstraints.append(pageControl!.trailingAnchor.constraint(lessThanOrEqualTo: trailingAnchor, constant: -5))
            }
            NSLayoutConstraint.activate(pageControlConstraints)
        } else {
            NSLayoutConstraint.activate([NSLayoutConstraint(item: imageCollectionView!, attribute: .top, relatedBy: .equal, toItem: self, attribute: .top, multiplier: 1, constant: 0),
                                         NSLayoutConstraint(item: imageCollectionView!, attribute: .bottom, relatedBy: .equal, toItem: self, attribute: .bottom, multiplier: 1, constant: 0),
                                         NSLayoutConstraint(item: imageCollectionView!, attribute: .leading, relatedBy: .equal, toItem: self, attribute: .leading, multiplier: 1, constant: 0),
                                         NSLayoutConstraint(item: imageCollectionView!, attribute: .trailing, relatedBy: .equal, toItem: self, attribute: .trailing, multiplier: 1, constant: 0)])
            var pageControlConstraints = [
                NSLayoutConstraint(item: pageControl!, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 20),
                NSLayoutConstraint(item: pageControl!, attribute: .bottom, relatedBy: .equal, toItem: self, attribute: .bottom, multiplier: 1, constant: -5)]
            switch dotLocation {
            case .centerBottom:
                pageControlConstraints.append(NSLayoutConstraint(item: pageControl!, attribute: .centerX, relatedBy: .equal, toItem: self, attribute: .centerX, multiplier: 1, constant: 0))
            case .leftBottom:
                pageControlConstraints.append(NSLayoutConstraint(item: pageControl!, attribute: .leading, relatedBy: .equal, toItem: self, attribute: .leading, multiplier: 1, constant: 5))
            case .rightBottom:
                pageControlConstraints.append(NSLayoutConstraint(item: pageControl!, attribute: .trailing, relatedBy: .equal, toItem: self, attribute: .trailing, multiplier: 1, constant: -5))
            }
            NSLayoutConstraint.activate(pageControlConstraints)
        }
        
        
        
    }
    
    fileprivate func startTimer() {
        if autoScroll {
            timer = Timer(timeInterval: duration, target: self, selector: #selector(automaticScroll), userInfo: nil, repeats: true)
            RunLoop.main.add(timer!, forMode: .commonModes)
        }
    }
    
    func automaticScroll() {
        let current = currentIndex()
        let nextIndex = current + 1
        scrollTo(index: nextIndex)
    }
    
    fileprivate func scrollTo(index: Int) {
        let nextIndex: IndexPath
        if index >= totalItemCount || index == 0 {
            nextIndex = IndexPath(item: totalItemCount / 2, section: 0)
        } else {
            nextIndex = IndexPath(item: index, section: 0)
        }
        imageCollectionView?.scrollToItem(at: nextIndex, at: [], animated: true)
    }
    
    fileprivate func currentIndex() -> Int {
        if imageCollectionView!.frame.size.width == 0 {
            return 0
        }
        return Int(floor(imageCollectionView!.contentOffset.x - (imageCollectionView!.frame.size.width / CGFloat(totalItemCount + 1))) / imageCollectionView!.frame.size.width) + 1
    }
    
}

// MARK: public methods
extension CycleBanner {
    
    /// 显示 Banner
    public func showBanner() {
        makeConstraints()
        startTimer()
    }
    
    public func reload() {
        imageCollectionView?.reloadData()
    }
    
}

// MARK: delegate and data source
extension CycleBanner: UICollectionViewDelegate, UICollectionViewDataSource {
    
    public func scrollViewDidScroll(_ scrollView: UIScrollView) {
        let page = currentIndex() % (dataSource?.numberOfImagesInCycleBanner())!
        pageControl?.currentPage = page
    }
    
    public func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
        // 用户滑动图片后重新开始计时
        if autoScroll {
            startTimer()
        }
    }
    
    public func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
        // 滑动图片时停止计时器
        if autoScroll {
            timer?.invalidate()
            timer = nil
        }
    }
    
    public func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        let current = currentIndex()
        if current >= totalItemCount || current == 0 {
            let index = IndexPath(item: totalItemCount / 2, section: 0)
            imageCollectionView?.scrollToItem(at: index, at: [], animated: false)
        }
    }
    
    public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        delegate?.cycleBanner(self, didSelectBannerAt: indexPath.row % (dataSource?.numberOfImagesInCycleBanner())!)
    }
    
    public func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 1
    }
    
    public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return (dataSource?.numberOfImagesInCycleBanner())! * 100
    }
    
    public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        var cell = collectionView.dequeueReusableCell(withReuseIdentifier: CycleBannerCellCommon.identifier, for: indexPath) as? CycleBannerCell
        if cell == nil {
            cell = CycleBannerCell()
        }
        cell?.imageView = (dataSource?.cycleBanner(self, imageViewForCellAt: indexPath.row % (dataSource?.numberOfImagesInCycleBanner())!))!
        cell?.imageView.translatesAutoresizingMaskIntoConstraints = false
        cell?.addSubview((cell?.imageView)!)
        cell?.bottomView.translatesAutoresizingMaskIntoConstraints = false
        switch dotLocation {
        case .centerBottom:
            break
        case .leftBottom:
            cell?.bottomView.addSubview((cell?.label)!)
            if let title = dataSource?.cycleBanner(self, titleForCellAt: indexPath.row % (dataSource?.numberOfImagesInCycleBanner())!) {
                cell?.bottomView.isHidden = false
                cell!.label.text = title
                cell?.label.textColor = UIColor.white
                cell?.bottomView.backgroundColor = UIColor.black.withAlphaComponent(0.6)
                cell?.label.textAlignment = .center
                cell?.label.translatesAutoresizingMaskIntoConstraints = false
                if #available(iOS 9.0, *) {
                    NSLayoutConstraint.activate([(cell?.label.trailingAnchor.constraint(equalTo: (cell?.bottomView.trailingAnchor)!))!,
                                                 (cell?.label.leadingAnchor.constraint(equalTo: (cell?.bottomView.leadingAnchor)!, constant: 15 * CGFloat((pageControl?.numberOfPages)!)))!])
                } else {
                    NSLayoutConstraint.activate([NSLayoutConstraint(item: cell!.label, attribute: .trailing, relatedBy: .equal, toItem: cell!.bottomView, attribute: .trailing, multiplier: 1, constant: 0),
                                                 NSLayoutConstraint(item: cell!.label, attribute: .leading, relatedBy: .equal, toItem: cell!.bottomView, attribute: .leading, multiplier: 1, constant: 15 * CGFloat((pageControl?.numberOfPages)!))])
                }
            } else {
                cell?.bottomView.isHidden = true
            }
            
        case .rightBottom:
            cell?.bottomView.addSubview((cell?.label)!)
            if let title = dataSource?.cycleBanner(self, titleForCellAt: indexPath.row % (dataSource?.numberOfImagesInCycleBanner())!) {
                cell?.bottomView.isHidden = false
                cell!.label.text = title
                cell?.label.textColor = UIColor.white
                cell?.bottomView.backgroundColor = UIColor.black.withAlphaComponent(0.6)
                cell?.label.numberOfLines = 1
                cell?.label.textAlignment = .center
                cell?.label.translatesAutoresizingMaskIntoConstraints = false
                
                if #available(iOS 9.0, *) {
                    NSLayoutConstraint.activate([(cell?.label.leadingAnchor.constraint(equalTo: (cell?.bottomView.leadingAnchor)!))!,
                                                 (cell?.label.trailingAnchor.constraint(equalTo: (cell?.bottomView.trailingAnchor)!, constant: -15 * CGFloat((pageControl?.numberOfPages)!)))!])
                } else {
                    NSLayoutConstraint.activate([NSLayoutConstraint(item: cell!.label, attribute: .leading, relatedBy: .equal, toItem: cell!.bottomView, attribute: .leading, multiplier: 1, constant: 0),
                                                 NSLayoutConstraint(item: cell!.label, attribute: .trailing, relatedBy: .equal, toItem: cell!.bottomView, attribute: .trailing, multiplier: 1, constant: -15 * CGFloat((pageControl?.numberOfPages)!))])
                }
            } else {
                cell?.bottomView.isHidden = true
            }
            
        }
        cell?.makeConstraints()
        
        return cell!
    }

}
