//
//  RuleCompareModelProtocol.swift
//  MVMCoreUI
//
//  Created by Matt Bruce on 3/9/22.
//  Copyright © 2022 Verizon Wireless. All rights reserved.
//

import Foundation

/// RuleCompareModelProtocol is meant to be used for rules that compare
///  2 FormField's values. It is up to the Implementing class to determine what
///  occurs within the "compare" method that is required.  This can be anything
///  that returns a Bool. More than likley it will be a <,>, <=, =>, == comparison.
public protocol RuleCompareModelProtocol: RulesProtocol {
    associatedtype CompareType
    func compare(lhs: CompareType?, rhs: CompareType?) -> Bool
}

extension RuleCompareModelProtocol {
    
    /// This overrides the RulesProtocol default implementation to then use your class implementation's "compare" method.
    /// A requirement of this rule is that the fields array contains at least 2 fieldKeys and it will pull out these formFields with ONLY
    /// the first 2 keys to send to the compare method your class will be implementing.
    public func validate(_ fieldMolecules: [String: FormFieldProtocol],_ previousFieldValidity: [String: FormFieldValidity]) -> (valid: Bool, fieldValidity: [String: FormFieldValidity]) {
        var valid = false
        
        guard fields.count > 1, let firstFormField = fieldMolecules[fields[0]],
              let secondFormField = fieldMolecules[fields[1]]  else {
                  return (valid: true, previousFieldValidity)
              }
        
        let result = compare(lhs: firstFormField.formFieldValue() as? CompareType, rhs: secondFormField.formFieldValue() as? CompareType)
        
        let formKey = fields[1]
        
        //only check the 2nd value
        if result {
            valid = true
            
            // If past rule is invalid for a field, the current rule should not flip the validity of a field
            if let validity = previousFieldValidity[formKey], !validity.valid, valid {
                valid = false
            }
            previousFieldValidity[formKey]?.valid = valid
            
        } else { //false
            previousFieldValidity[formKey]?.valid = valid
            previousFieldValidity[formKey]?.addError(message: errorMessage?[formKey])
        }
        
        return (valid: valid, fieldValidity: previousFieldValidity)
        
    }
}
