//
//  MessageModel.swift
//  PaiAi
//
//  Created by zhengjianfei on 16/4/7.
//  Copyright © 2016年 FFIB. All rights reserved.
//

import Foundation
import ObjectMapper
import RxCocoa
import RxDataSources

import Foundation
import RxCocoa
import RxSwift

public protocol MessageRepositorable: Repositorable where Content == [GroupItem] {}

final public class MessageRepository: Resource {
    fileprivate var items: BehaviorRelay<[GroupItem]>
    fileprivate var hasMore: Bool
    fileprivate var page: Int
    fileprivate var loadingSchedule: PublishSubject<Bool>
    
    var path: Interfaces { return .groupList }
    #warning("admin_id 填充")
    var parameter: Parameter = ["admin_id": ""]
    fileprivate var deleteResource: GroupDeleteResource
    
    
    init() {
        page = 1
        hasMore = true
        loadingSchedule = PublishSubject<Bool>()
        items = BehaviorRelay<[GroupItem]>(value: [])
        deleteResource = GroupDeleteResource()
    }
}

extension GroupRepository: Parsable {
    typealias Model = [GroupItem]
    
    func parse(_ json: JSON) -> [GroupItem]? {
        guard let data = json["data"] as? [String: AnyObject],
            let messages = data["groups"] as? [[String: AnyObject]],
            let left = data["left"] as? Int else { return nil }
        hasMore = left > 0
        return messages.map { return GroupItem(json: $0) }
    }
}

extension GroupRepository: Gettable {
    public func loadContent(isRefresh: Bool) {
        guard hasMore else {
            loadingSchedule.onNext(isRefresh)
            return
        }
        
        page = isRefresh ? 1 : page + 1
        parameter["page"] = page
        let _ = NetworkApi.share.post(resource: self) { result in
            
            defer { self.loadingSchedule.onNext(isRefresh) }
            
            guard case let .success(items) = result else {
                return
            }
            
            if isRefresh {
                self.items.accept(items)
            } else {
                self.items.accept(self.items.value + items)
            }
        }
    }
}

extension GroupRepository: Deletable {
    func remove(of index: Int) {
        let item = items.value[index]
        deleteResource.parameter["group_id"] = item.group_id
        NetworkApi.share.post(resource: deleteResource) { [weak self] result in
            guard case let .success(statusModel) = result else { return }
            guard let `self` = self else { return }
            if statusModel.status == 200 {
                var values = self.items.value
                values.remove(at: index)
                self.items.accept(values)
            } else if statusModel.status == 402010 {
                #warning("无权限")
            } else if statusModel.status == 402099 {
                #warning("无权限")
            }
        }
    }
}

extension GroupRepository: GroupRepositorable {
    public var content: Observable<[GroupItem]> {
        return items.asObservable()
            .flatMap { currentItems in
                Observable.just(currentItems)
                    .distinctUntilChanged()
            }.share()
    }
    
    public var loadingObserver: Observable<Bool> {
        return loadingSchedule.asObserver()
            .flatMap { current in
                Observable.just(current)
            }.share()
    }
}


protocol MessageInteractionModel {
    var path: Interfaces { get }
    var deletePath: Interfaces { get }
    var readPath: Interfaces { get }
    var title: String { get }
}


public enum MessageType: String {
    case zan = "zan"
    case comment = "comment"
    case system = "system"
    
    fileprivate var messageInteractionModel: MessageInteractionModel {
        switch self {
        case .zan: return MessageZanInteractionModel()
        case .comment: return MessageCommentInteractionModel()
        case .system: return MessageSystemInteractionModel()
        }
    }
    
    fileprivate struct MessageZanInteractionModel: MessageInteractionModel {
        var path: Interfaces { return .mesThumbupList}
        var deletePath: Interfaces { return .mesThumbupClear }
        var readPath: Interfaces { return .mesThumbupRead }
        var title: String { return "赞" }
    }
    
    fileprivate struct MessageCommentInteractionModel: MessageInteractionModel {
        var path: Interfaces { return .mesCommentList}
        var deletePath: Interfaces { return .mesCommentClear }
        var readPath: Interfaces { return .mesCommentRead }
        var title: String { return "评论" }
    }
    
    fileprivate struct MessageSystemInteractionModel: MessageInteractionModel {
        var path: Interfaces { return .mesSystemList}
        var deletePath: Interfaces { return .mesSystemClear }
        var readPath: Interfaces { return .mesSystemRead }
        var title: String { return "系统消息" }
    }
}



final class MessageModel {
    private(set) var items: BehaviorRelay<[MessageItem]>
    private var hasMore = true
    private var page = 1
    private var contentsResource: Resource<[MessageItem]>?
    private var deleteItemResource: Resource<StatusModel>?
    private var readMessageResource: Resource<StatusModel>?
    
    
    init(type: MessageType) {
        items = BehaviorRelay<[MessageItem]>(value: [])
        
        contentsResource =  Resource(url: type.messageInteractionModel.path,
                                     param: ["user_id": SharedUserInfo.userId as AnyObject],
                                     parse: parse)
        deleteItemResource = Resource(url: type.messageInteractionModel.deletePath,
                                      param: ["user_id": SharedUserInfo.userId as AnyObject],
                                      parse: parseStatus)
        readMessageResource = Resource(url: type.messageInteractionModel.readPath,
                                       param: ["user_id": SharedUserInfo.userId as AnyObject,
                                               "all": "true" as AnyObject],
                                       parse: parseStatus)
    }
    
    private func parse(json: [String: AnyObject]) -> [MessageItem]? {
        guard let data = json["data"],
            let messages = data["messages"] as? [[String: AnyObject]],
            let left = data["left"] as? Int else { return nil }
        hasMore = left > 0
        return messages.map { return MessageItem(json: $0) }
    }
    
    private func parseStatus(json: [String: AnyObject]) -> StatusModel? {
        return StatusModel(json: json)
    }
    
    func loadContents(isRefresh: Bool) {
        guard hasMore else { return }
        page = isRefresh ? 1 : page + 1
        contentsResource!.parameter["page"] = page as AnyObject
        NetworkApi.share.post(resource: contentsResource!) { [weak self] result in
            guard case let .success(messageItems) = result else { return }
            guard let `self` = self else { return }
            if isRefresh {
                self.items.accept(messageItems)
            } else {
                self.items.accept(self.items.value + messageItems)
            }
            
        }
    }
    
    func remove(_ item: MessageItem) {
        guard let index = items.value.index(where: { $0 == item }) else { return }
        deleteItemResource!.parameter["pk"] = items.value[index].pk as AnyObject
        NetworkApi.share.post(resource: deleteItemResource!) { [weak self] result in
            guard case .success(_) = result else { return }
            guard let `self` = self else { return }

            var values = self.items.value
            values.remove(at: index)
            self.items.accept(values)
        }
    }
    
    func removeAll(_ completion:@escaping () -> ()) {
        deleteItemResource!.parameter["all"] = true as AnyObject
        NetworkApi.share.post(resource: deleteItemResource!) { [weak self] result in
            guard case .success(_) = result else { return }
            guard let `self` = self else { return }
            self.items.accept([])
            completion()
        }
    }
    
    func readMessage() {
        NetworkApi.share.post(resource: readMessageResource!, completion: {_ in })
    }
}