//
//  UIViewController+HXExtension.swift
//  HXSwift
//
//  Created by lizhengyi on 2018/2/24.
//  Copyright © 2018年 lizhengyi. All rights reserved.
//

import UIKit

/*HXExtension*****************************************************************************/
fileprivate struct AssociatedKeys {
    static var title: Void?
    static var titleLabel: Void?
    static var leftBarButtonItemImageName: Void?
    static var leftBarButtonItemTitle: Void?
    static var leftBarButtonItemAction: Void?
    static var rightBarButtonItemImageName: Void?
    static var rightBarButtonItemTitle: Void?
    static var rightBarButtonItemAction: Void?
    static var leftBarButton: Void?
    static var rightBarButton: Void?
}

extension HX where Base: UIViewController {
    public var title: String? {
        get {
            return objc_getAssociatedObject(base, &AssociatedKeys.title) as? String
        }
        set {
            if let label = objc_getAssociatedObject(base, &AssociatedKeys.titleLabel) as? UILabel {
                label.text = newValue
                base.navigationItem.titleView = label
            } else {
                let label = UILabel().then { this in
                    this.frame = CGRect(84, 0, kScreenWidth - 168, 44)
                    this.textColor = UIColor.white
                    this.font = UIFont.boldSystemFont(ofSize: 18)
                    this.textAlignment = .center
                    this.text = newValue
                }
                objc_setAssociatedObject(base, &AssociatedKeys.titleLabel, label, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
                base.navigationItem.titleView = label
            }
            objc_setAssociatedObject(base, &AssociatedKeys.title, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
    
    public var pushedViewController: UIViewController? {
        guard let index = base.navigationController?.viewControllers.index(of: base) else {
            return nil
        }
        if base.navigationController!.viewControllers.count <= index {
            return nil
        }
        return base.navigationController?.viewControllers[index - 1]
    }
    
    public func push(_ viewController: UIViewController) {
        base.navigationController?.pushViewController(viewController, animated: true)
    }
    
    public func pop() {
        base.navigationController?.popViewController(animated: true)
    }
    
    public func popToRoot() {
        base.navigationController?.popToRootViewController(animated: true)
    }
    
    public var leftBarButton: UIButton? {
        return objc_getAssociatedObject(base, &AssociatedKeys.leftBarButton) as? UIButton
    }
    
    public var rightBarButton: UIButton? {
        return objc_getAssociatedObject(base, &AssociatedKeys.rightBarButton) as? UIButton
    }
    
    public var leftBarButtonItem: (imageName: String?, title: String?, action: Selector?)? {
        get {
            let imageName = objc_getAssociatedObject(base, &AssociatedKeys.leftBarButtonItemImageName) as? String
            let title = objc_getAssociatedObject(base, &AssociatedKeys.leftBarButtonItemTitle) as? String
            let action = objc_getAssociatedObject(base, &AssociatedKeys.leftBarButtonItemAction) as? Selector
            if imageName == nil,
                title == nil,
                action == nil {
                return nil
            }
            return (imageName: imageName, title: title, action: action)
        }
        set {
            if let someLeftBarButtonItem = newValue {
                var btn = self.leftBarButton
                if btn == nil {
                    btn = UIButton(type: .custom)
                    objc_setAssociatedObject(base, &AssociatedKeys.leftBarButton, btn, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
                }
                btn!.setTitle(someLeftBarButtonItem.title, for: .normal)
                btn!.titleLabel?.font = UIFont.systemFont(ofSize: 14)
                if someLeftBarButtonItem.imageName != nil {
                    btn!.setImage(UIImage.init(named: someLeftBarButtonItem.imageName!), for: .normal)
                }
                btn!.sizeToFit()
                if someLeftBarButtonItem.action != nil {
                    btn?.addTarget(base, action: someLeftBarButtonItem.action!, for: .touchUpInside)
                }
                let barButtonItem = UIBarButtonItem(customView: btn!)
                base.navigationItem.leftBarButtonItem = barButtonItem
                base.navigationItem.hidesBackButton = false
            } else {
                //MARK: left有点特殊 —— nil
                base.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: UIButton())
            }
            objc_setAssociatedObject(base, &AssociatedKeys.leftBarButtonItemImageName, newValue?.imageName, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
            objc_setAssociatedObject(base, &AssociatedKeys.leftBarButtonItemTitle, newValue?.title, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
            objc_setAssociatedObject(base, &AssociatedKeys.leftBarButtonItemAction, newValue?.action, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
    
    public var popBarButtonItem: (imageName: String?, title: String?, action: Selector?) {
        return ("btn_nav_back", nil, #selector(base.pop))
    }
    
    public var rightBarButtonItem: (imageName: String?, title: String?, action: Selector?)? {
        get {
            let imageName = objc_getAssociatedObject(base, &AssociatedKeys.rightBarButtonItemImageName) as? String
            let title = objc_getAssociatedObject(base, &AssociatedKeys.rightBarButtonItemTitle) as? String
            let action = objc_getAssociatedObject(base, &AssociatedKeys.rightBarButtonItemAction) as? Selector
            if imageName == nil,
                title == nil,
                action == nil {
                return nil
            }
            return (imageName: imageName, title: title, action: action)
        }
        set {
            if let someRightBarButtonItem = newValue {
                var btn = self.rightBarButton
                if btn == nil {
                    btn = UIButton(type: .custom)
                    objc_setAssociatedObject(base, &AssociatedKeys.rightBarButton, btn, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
                }
                btn!.setTitle(someRightBarButtonItem.title, for: .normal)
                btn!.titleLabel?.font = UIFont.systemFont(ofSize: 14)
                if someRightBarButtonItem.imageName != nil {
                    btn!.setImage(UIImage.init(named: someRightBarButtonItem.imageName!), for: .normal)
                }
                btn!.sizeToFit()
                if someRightBarButtonItem.action != nil {
                    btn!.addTarget(base, action: someRightBarButtonItem.action!, for: .touchUpInside)
                }
                let barButtonItem = UIBarButtonItem(customView: btn!)
                base.navigationItem.rightBarButtonItem = barButtonItem
            } else {
                base.navigationItem.rightBarButtonItem = nil
            }
            objc_setAssociatedObject(base, &AssociatedKeys.rightBarButtonItemImageName, newValue?.imageName, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
            objc_setAssociatedObject(base, &AssociatedKeys.rightBarButtonItemTitle, newValue?.title, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
            objc_setAssociatedObject(base, &AssociatedKeys.rightBarButtonItemAction, newValue?.action, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
    
    public func configureRefreshResult(with scrollView: UIScrollView, result: RefreshResult) {
        switch result {
        case let .loading(state: state):
            if state == .refresh {
                ShowProcessActivity()
            }
        case let .succeeded(state):
            if state == .refresh {
                if let header = scrollView.mj_header { header.endRefreshing() }
                if let footer = scrollView.mj_footer { footer.state = .idle }
                HideProcessActivity()
            } else if state == .append {
                if let footer = scrollView.mj_footer { footer.endRefreshing() }
            } else {
                HideProcessActivity()
            }
        case let .failed(state, error):
            if state == .refresh || state == .idle {
                if let header = scrollView.mj_header { header.endRefreshing() }
                if let footer = scrollView.mj_footer { footer.endRefreshing() }
                HideProcessActivity()
            } else if state == .append {
                ShowError(error: error)
                if case NetworkError.noData = error {
                    if let footer = scrollView.mj_footer { footer.endRefreshingWithNoMoreData() }
                } else {
                    if let footer = scrollView.mj_footer { footer.endRefreshing() }
                }
            }
        }
    }
    
    public func configureOperateResult(with result: OperationResult) {
        switch result {
        case .idle:
            return
        case .operating:
            ShowProcessActivity()
        case let .succeeded(message):
            HideProcessActivity()
            if message != nil {
                ShowToast(text:message!)
            }
        case let .failed(error):
            HideProcessActivity()
            ShowError(error: error)
        }
    }
}

extension HX where Base: UIViewController {
    public func dismissViewController() {
        if base.isBeingDismissed || base.isBeingPresented {
            DispatchQueue.main.async {
                self.dismissViewController()
            }
            return
        }
        if base.presentingViewController != nil {
            base.dismiss(animated: true, completion: nil)
        }
    }
}
/******************************************************************************End*/







