//
//  BaseCoordinator.swift
//  Paiai_iOS
//
//  Created by FFIB on 2019/4/29.
//  Copyright © 2019 FFIB. All rights reserved.
//

import RxSwift
import Foundation

public class BaseCoordinator<ResultType> {

    typealias CoordinationResult = ResultType

    let disposeBag = DisposeBag()
    var didCancel = PublishSubject<Void>()
    var navigationController: UINavigationController
    var viewController: UIViewController

    private let identifier = UUID()
    private var childCoordinators = [UUID: Any]()

    init(navigationController: UINavigationController, viewController: UIViewController) {
        self.viewController = viewController
        self.navigationController = navigationController
        listenDeallocate()
    }

    private func store<T>(coordinator: BaseCoordinator<T>) {
        childCoordinators[coordinator.identifier] = coordinator
    }

    private func free<T>(coordinator: BaseCoordinator<T>) {
        childCoordinators[coordinator.identifier] = nil
    }

    func coordinate<T>(to coordinator: BaseCoordinator<T>) -> Observable<T> {
        store(coordinator: coordinator)
        return coordinator.start()
            .do(onNext: { [weak self] _ in
                self?.free(coordinator: coordinator)
            })
    }

    func start() -> Observable<ResultType> {
        fatalError("Start method should be implemented.")
    }

    func listenDeallocate() {
        navigationController.rx.willShow.subscribe(onNext: {[weak self] (_, _) in
            guard let `self` = self else { return }
            if !self.navigationController.viewControllers.contains(self.viewController) {
                self.didCancel.onNext(())
            }
        }).disposed(by: disposeBag)
    }
}