//
//  ModelTemplateProtocol.swift
//  MVMCoreUI
//
//  Created by Suresh, Kamlesh on 11/25/19.
//  Copyright © 2019 Verizon Wireless. All rights reserved.
//

import Foundation

public protocol TemplateProtocol: AnyObject {
    associatedtype TemplateModel: TemplateModelProtocol
    var templateModel: TemplateModel? { get set }
    
    func decodeTemplate(using decoder: JSONDecoder, from data: Data) throws -> TemplateModel
}

public extension TemplateProtocol where Self: ViewController {
    
    func parseTemplate(json: [AnyHashable: Any]?) throws {
        guard let pageJSON = json else { return }
        let data = try JSONSerialization.data(withJSONObject: pageJSON)
        let decoder = JSONDecoder()
        try decoder.add(delegateObject: delegateObjectIVar)
        templateModel = try decodeTemplate(using: decoder, from: data)
        model = templateModel as? MVMControllerModelProtocol
        guard let model = model else { return }
        traverseAndAddRequiredBehaviors()
        var behaviorHandler = self
        behaviorHandler.createBehaviors(for: model, delegateObject: delegateObjectIVar)
    }
    
    func decodeTemplate(using decoder: JSONDecoder, from data: Data) throws -> TemplateModel {
        try decoder.decode(TemplateModel.self, from: data)
    }
    
    /// Traverses all models and adds any required behavior models.
    func traverseAndAddRequiredBehaviors() {
        guard var model = model else { return }
        let behaviorModels: [PageBehaviorModelProtocol] = model.reduceDepthFirstTraverse(options: .childFirst, depth: 0, initialResult: []) { (accumulator, molecule, depth) in
            if let behaviorRequirer = molecule as? PageBehaviorProtocolRequirer {
                return accumulator + behaviorRequirer.getRequiredBehaviors()
            }
            return accumulator
        }
        for behavior in behaviorModels {
            model.add(behavior: behavior)
        }
    }
}
