//
//  GMBaseController.swift
//  Gengmei
//
//  Created by wangyang on 16/3/21.
//  Copyright © 2016年 更美互动信息科技有限公司. All rights reserved.
//

import UIKit
import GMPhobos
import GMKit

private var navigationBarAssociationKey: UInt8 = 0

open class GMBaseController: UIViewController, GMNavigationBarDelegate, GMEmptyViewDelegate {

    public var emptyView = GMEmptyView(frame:CGRect(x: 0, y: 0, width: Constant.screenWidth, height: Constant.screenHeight))
    /**
     默认值为false，表示导航栏自动被WMBaseViewController管理，永远在所有的view最上方。
     设置为true时表示因为特殊需求，开发人员需要自己控制导航，并且需要在viewDidLoad中确定navigationBar的位置
     */
    public var controlNavigationByYou = false

    public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
        initController()
    }

    public required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        initController()
    }

    open func initController() {
        // 在 initController 中初始化自定义导航栏有很大好处。至少可以保证视图被push之前就可以访问navigationBar，以配置title等属性
        customNavigationBar()
        edgesForExtendedLayout = UIRectEdge()
        automaticallyAdjustsScrollViewInsets = false
    }

    open override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = UIColor.background
        if responds(to: #selector(setter: UIViewController.edgesForExtendedLayout)) {
            edgesForExtendedLayout = UIRectEdge()
        }

        addNavigationBar()
        hideLeftButtonForRootController()
        initReferer()
        initRefererLink()
        initReferrerTabName()
        setupEmptyView()
    }

    open override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        // 保证即使在loading的时候，仍然可以后退
        if !controlNavigationByYou {
            view.bringSubview(toFront: navigationBar)
        }
    }

    open override func didMove(toParentViewController parent: UIViewController?) {
        // 作为childController使用，但不是被push到 UINavigationController时，隐藏导航栏
        super.didMove(toParentViewController: parent)
        if parent != nil && !(parent is UINavigationController) {
            navigationBar.isHidden = true
        }
    }

    open override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        // 导航栏隐藏在 viewWillAppear 里控制的原因是在viewDidLoad时，有可能 navigationController 与 self 并没有关系
        if navigationController != nil {
            navigationController!.isNavigationBarHidden = true
        }
        Phobos.sharedClient().onPVStart(self)
    }

    open override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        if !pageName.isEmpty {
            Phobos.sharedClient().onPVEnd(self)
        }
    }

    open override var preferredStatusBarStyle: UIStatusBarStyle {
        if #available(iOS 13.0, *) {
            return UIStatusBarStyle.darkContent
        } else {
            return UIStatusBarStyle.default
        }
    }

    deinit {
        NotificationCenter.default.removeObserver(self)
    }

    // MARK: - 导航相关
    public var navigationBar: GMNavigationBar {
        get {
            return objc_getAssociatedObject(self, &navigationBarAssociationKey) as! GMNavigationBar
        }
        set(newValue) {
            objc_setAssociatedObject(self, &navigationBarAssociationKey, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
        }
    }

    public func customNavigationBar() {
        navigationBar = GMNavigationBar()
    }

    public func addNavigationBar() {
        navigationBar.delegate = self
        view.addSubview(navigationBar)
    }

    public func hideLeftButtonForRootController() {
        if navigationController != nil && navigationController!.viewControllers.count == 1 {
            navigationBar.leftButton.isHidden = true
        }
    }

    /// 对于没有导航栏，但是有backButton的controller，可以使用这个方法创建backButton。坐标需要指定
    open func createBackButton(_ imageName: String) -> UIButton {
        let button = GMBaseNavigationButton(type: .custom)
        button.setImage(UIImage(named: imageName), for: .normal)
        button.sizeToFit()
        button.adaptiveHotAreaWidth = 70
        button.addTarget(self, action: #selector(GMBaseController.backAction(_:)), for: .touchUpInside)
        return button
    }

    open func pushViewController(_ controller: UIViewController) {
        navigationController?.pushViewController(controller, animated: true)
    }

    open func rightButtonClicked(_ button: UIButton) {

    }

    open func backAction(_ button: UIButton) {
        // parentViewController 是 UINavigationController 说明是极有可能是 push 进来的，需要进一步判断
        if (parent?.isKind(of: UINavigationController.classForCoder())) != nil {
            let navigation = (parent as! UINavigationController)
            // 如果 presentingViewController 存在，表示有人 present 自己，再并上条件已经在导航器上rootViewController时，直接 dismiss 就好了
            if presentingViewController != nil && navigation.viewControllers.count == 1 {
                dismiss(animated: true, completion: nil)
            } else {
                _ = navigationController?.popViewController(animated: true)
            }
        } else {
            dismiss(animated: true, completion: nil)
        }
    }

}

@objc extension GMBaseController {
    // MARK: - GMEmptyView
    @objc open func setupEmptyView() {
        emptyView.isHidden = true
        emptyView.delegate = self
        view.addSubview(emptyView)
        emptyView.snp.makeConstraints { (make) in
            if let _ = self.parent as? UINavigationController {
                make.top.equalTo(UIApplication.shared.statusBarFrame.height)
            } else {
                make.top.equalTo(0)
            }
            make.left.right.bottom.equalTo(0)
        }
    }

    @objc open func showEmptyView(_ type: GMEmptyViewType) {
        emptyView.type = type
        emptyView.isHidden = false
        view.bringSubview(toFront: emptyView)
    }

    @objc open func hideEmptyView() {
        emptyView.isHidden = true
    }

    @objc open func emptyViewDidClickReload() {
        if let me = self as? Refreshable {
            me.refreshList()
        }
    }
}

