//
//  LKFDataStructureCheck.swift
//  lkfc
//
//  Created by Alexander Holzer on 29.03.23.
//  Copyright © 2023 Alexander Holzer. All rights reserved.
//

import Foundation
@_implementationOnly import LibLKF

public class LKFRecordTypeCheck {
    
    public let field: LKFRecordTypeField
    public let fondsOnly: Bool
    public let checkType : String
    public let error : String
    public let errorText : String
    public let functionDescription : [String]?
    
    public let trueChild : LKFRecordTypeCheck?
    public let falseChild : LKFRecordTypeCheck?
    
    public var recordType : LKFRecordType {
        return field.recordType
    }
    
    init (field: LKFRecordTypeField, checkType: String, error: String, errorText: String, functionDescription : [String]?, trueChild: LKFRecordTypeCheck? = nil, falseChild: LKFRecordTypeCheck? = nil) {
        self.field = field
        
        if checkType.hasPrefix("*/") {
            self.fondsOnly = true
            self.checkType = String(checkType.dropFirst(2))
        }
        else {
            self.checkType = checkType
            self.fondsOnly = false
        }
        
        self.error = error
        self.errorText = errorText
        self.functionDescription = functionDescription
        self.trueChild = trueChild
        self.falseChild = falseChild
    }
    
    convenience init? (field: LKFRecordTypeField, checkInfo: UnsafeRawPointer, lineBuffer: UnsafeMutablePointer<CChar>) {
        
        guard let lkfContext = field.lkfContext, LibLKF.lkf_Satzart_getCheckInfo(lkfContext.ptr!, checkInfo, "", "", lineBuffer, 2048) > 0 else {
            return nil
        }
        
        let parts = String(cString:lineBuffer).components(separatedBy: ";")
        
        guard parts.count >= 6 else {
            return nil
        }
        
        let checkType = parts[3].trimmingCharacters(in: .whitespaces)
        let error = parts[4].trimmingCharacters(in: .whitespaces)
        let errorText = parts[5].trimmingCharacters(in: .whitespaces)
        let functionDescription : [String]?
        let trueChild : LKFRecordTypeCheck?
        let falseChild : LKFRecordTypeCheck?
        
        if LibLKF.lkf_Satzart_getCheckDetails (lkfContext.ptr!, checkInfo, lineBuffer, 2048) > 0 {
            functionDescription = String(cString:lineBuffer).components(separatedBy: "\n")
        }
        else {
            functionDescription = nil
        }
        
        let nextCheck = LibLKF.lkf_Satzart_getNextCheck(lkfContext.ptr!, checkInfo, 1)
        if let nextCheck {
            trueChild = LKFRecordTypeCheck (field: field, checkInfo: nextCheck, lineBuffer: lineBuffer)
        }
        else {
            trueChild = nil
        }
        
        if let nextCheckErr = LibLKF.lkf_Satzart_getNextCheck(lkfContext.ptr!, checkInfo, 0) {
            if nextCheckErr == nextCheck {
                falseChild = trueChild
            }
            else {
                falseChild = LKFRecordTypeCheck (field: field, checkInfo: nextCheckErr, lineBuffer: lineBuffer)
            }
        }
        else {
            falseChild = nil
        }
        
        self.init(field:field, checkType: checkType, error: error, errorText: errorText, functionDescription: functionDescription, trueChild: trueChild, falseChild: falseChild)
    }
    
    public func checkMustField() -> LKFRecordTypeCheck? {
        if checkType == "LEER" || checkType == "LEER/0" {
            return LKFRecordTypeCheck(field: field, checkType: self.checkType, error: self.error, errorText: self.errorText, functionDescription: self.functionDescription)
        }
        return nil
    }
    
    public func checkFormatField() -> LKFRecordTypeCheck? {
        if checkType == "LEER" || checkType == "LEER/0" {
            return trueChild?.checkFormatField()
        }
        if checkType == "FORMAT" {
            return LKFRecordTypeCheck(field: field, checkType: self.checkType, error: self.error, errorText: self.errorText, functionDescription: self.functionDescription)
        }
        return nil
    }

    public func checkIgnoreMustAndFormatField() -> LKFRecordTypeCheck? {
        if checkType == "LEER" || checkType == "LEER/0" {
            return trueChild?.checkIgnoreMustAndFormatField()
        }
        if checkType == "FORMAT" {
            return trueChild?.checkIgnoreMustAndFormatField()
        }
        return self
    }
    
    public func checksFor (errorCode: String) -> [LKFRecordTypeCheck]? {
        if errorCode == self.error {
            return [self]
        }
        if let trueChild, let c = trueChild.checksFor(errorCode: errorCode) {
            return c
        }
        return falseChild?.checksFor(errorCode: errorCode)        
    }
}
