//
//  GroupViewModel.swift
//  PaiaiDataKit
//
//  Created by FFIB on 2017/1/4.
//  Copyright © 2017年 FFIB. All rights reserved.
//

import Foundation
import RxSwift
import RxCocoa
import RxDataSources

public protocol GroupViewModelDelegate: class {
    func didSelect(_ items: [PhotoItem], currIndex: Int)
    func navigateToGroupDetail(_ item: GroupItem)
}

public class GroupViewModel {

    private let disposeBag = DisposeBag()

    private var repository: GroupPhotoRepository

    private var _isLoading = PublishSubject<Void>()
    private let _items: BehaviorRelay<[PhotoItem]>
    private let _hasData = BehaviorRelay<Bool>(value: false)

    public var groupItem: BehaviorRelay<GroupItem>

    public var group_name: Observable<String> {
        return groupItem.asObservable().flatMapLatest({ (item) -> Observable<String> in
            return Observable.just(item.group_name)
        })
    }

    public var group_avatar: Observable<String> {
        return groupItem.asObservable().flatMapLatest({ (item) -> Observable<String> in
            return Observable.just("Group\(item.group_default_avatar)")
        })
    }

    public var isLoading: Observable<Void> {
        return _isLoading.asObservable()
    }

    public var hasData: Observable<Bool> {
        return _hasData.asObservable()
    }

    public var contents: Observable<[AnimatableSectionModel<Int, PhotoItem>]> {
        return _items.map({ model in
            return [AnimatableSectionModel(model: 0, items: model)]
        })
    }

    public weak var delegate: GroupViewModelDelegate?

    public init(groupItem: GroupItem, items: [PhotoItem] = []) {
        self._items = BehaviorRelay<[PhotoItem]>(value: items)
        self.repository = GroupPhotoRepository(groupId: groupItem.group_id)
        self.groupItem = BehaviorRelay<GroupItem>(value: groupItem)
        RecentGroupInfo.share.add(groupItem)
        setNotification()
    }

    public func reload() {
        repository.load()
            .subscribe(onSuccess: {[weak self] (result) in
                guard let `self` = self else { return }
                self._isLoading.onNext(())
                self._items.accept(result)
                self._hasData.accept(result.count > 0)
                }, onError: {[weak self] (_) in
                    guard let `self` = self else { return }
                    self._isLoading.onNext(())
            }).disposed(by: disposeBag)
    }

    public func submit(data: Data) {
        repository.upload(data: data).subscribe(onSuccess: { [weak self] result in
            guard let `self` = self else { return }
            self._items.accept(result)
            var item = self.groupItem.value
            item.group_photo_num = result.count

            let userInfo = [GroupItemsOperator.key: GroupItemsOperator.update(self.groupItem.value.group_id, item)]
            NotificationCenter.default.post(name: .GroupItemsChanged,
                                            object: nil,
                                            userInfo: userInfo)
            Toast.show(message: "照片已上传")
            self._isLoading.onNext(())
            }, onError: {[weak self] _ in
            guard let  `self` = self else { return }
            Toast.show(message: "照片失败")
            self._isLoading.onNext(())
        }).disposed(by: disposeBag)
    }

    public func layoutSizeForIndexPath(_ indexPath: IndexPath) -> CGSize {
        let item = _items.value[indexPath.row]
        let width = item.photo_thumbnail_w
        let height = item.photo_thumbnail_h

        //        header 42, footer: 32
        return CGSize(width: width, height: height + 74)
    }

    private func setNotification() {
        NotificationCenter.default.rx.notification(.GroupItemsChanged).subscribe(onNext: { (notification) in
            guard let itemOperator = notification.userInfo?[GroupItemsOperator.key] as? GroupItemsOperator,
                case let .update(_, val) = itemOperator else { return }
            self.groupItem.accept(val)
            RecentGroupInfo.share.add(val)

            var items = self._items.value
            items = items.map({ item in
                var tmp = item
                tmp.group_name = val.group_name
                return tmp
            })
            self._items.accept(items)

        }).disposed(by: disposeBag)

        NotificationCenter.default.rx.notification(.PhotoItemsChanged).subscribe(onNext: { (notification) in
            guard let itemOperator = notification.userInfo?[PhotoItemsOperator.key] as? PhotoItemsOperator,
                case let .update(id, val) = itemOperator,
                let index = self._items.value.firstIndex(where: { $0.photo_id == id }) else { return }
            var items = self._items.value
            items[index] = val
            self._items.accept(items)
        }).disposed(by: disposeBag)
    }
}

/// GroupViewModelDelegate
public extension GroupViewModel {
    func didSelect(_ index: Int) {
        delegate?.didSelect(_items.value, currIndex: index)
    }

    @objc func navigateToGroupDetail() {
        delegate?.navigateToGroupDetail(groupItem.value)
    }
}