//
//  LKFOutputErrorFile.swift
//  lkfc
//
//  Created by Alexander Holzer on 07.06.18.
//  Copyright © 2018 Alexander Holzer. All rights reserved.
//

import Foundation
@_implementationOnly import LibLKF

public enum LKFErrorField : UInt32 {
    case kanr = 2
    case aufnr = 3
    case aufdat = 40
    case gebdat = 4
    case geschl = 6
    case entdat = 16
    case satzart = 101
    case code = 102
    case ident = 103
    case massnahme = 104
    case text = 105
    case acceptable = 119
    case text150 = 150
    case text150byte = 111
    case feld = 106
    case feldid = 107
    case feldname = 108
    case feld_lang = 109
    case berichtstyp = 120
    case entabt = 38
    case aufabt = 77
    case abtfc = 71
    case abtfcent = 72
    case abtfcindex = 73
    case abtfcentindex = 74
    case entabtindex = 75
    case kst = 81
    case entkst = 82
    case kst_entkst = 83
    case aufid64 = 13
    case alter = 14
    case alter2 = 12
    case fucoaufnr = 15
    case childIdent = 18
    case caseindex = 99
    case mbds_mel = 10011
    
    public var shortLabel : String {
        switch (self) {
        case .kanr:              return "KANR"
        case .aufnr:             return "AUFNR"
        case .aufdat:            return "AUFDAT"
        case .geschl:            return "GESCHL"
        case .entdat:            return "ENTDAT"
        case .satzart:           return "SATZART"
        case .code:              return "CODE"
        case .ident:             return "IDENT"
        case .massnahme:         return "MASSNAHME"
        case .text:              return "TEXT"
        case .text150byte:       return "TEXT"
        case .feld:              return "FELD"
        case .feldid:            return "FELD-ID"
        case .feldname:          return "FELD-NAME"
        case .feld_lang:         return "FELD"
        case .berichtstyp:       return "BERICHTSTYP"
        case .entabt:            return "ENTABT"
        case .abtfc:             return "ABTFC"
        case .abtfcent:          return "ABTFCENT"
        case .abtfcindex:        return "ABTFCINDEX"
        case .abtfcentindex:     return "ABTFCENTINDEX"
        case .entabtindex:       return "ENTABTINDEX"
        case .kst:               return "KST"
        case .entkst:            return "ENTKST"
        case .kst_entkst:        return "KST/ENTKST"
        case .aufid64:           return "AUFID"
        case .alter:             return "ALTER"
        case .alter2:            return "ALTER"
        case .fucoaufnr:         return "FUCOAUFNR"
        case .childIdent:        return "CHILDIDENT"
        case .mbds_mel:          return "MBDS-MEL"
        case .gebdat:            return "GEBDAT"
        case .acceptable:        return "ACCEPTABLE"
        case .text150:           return "TEXT"
        case .aufabt:            return "AUFABT"
        case .caseindex:         return "CASEINDEX"
        }
    }
    
}
public class LKFOutputErrorFile : LKFOutputFilePackaged {
    
    var errorFormatFields : [UInt32:[UInt32]?]?
    var facility : UInt32 = 0
    let withHeadline : Bool
    var errorTypes: UInt32 = 255
    
    public init (context: LKFContext, withHeadline: Bool = true) {
        self.withHeadline = withHeadline
        super.init(context: context)
    }
    
    public func setErrorFormat (facility:UInt32, fieldIndices:[UInt32]?) {
        if errorFormatFields == nil {
            errorFormatFields = [:]
        }
        errorFormatFields![facility] = fieldIndices
    }
    
    public func setErrorFormat (facility:UInt32 = 0, fields:[LKFErrorField]?) {
        
        if let fields = fields {
            setErrorFormat(facility: facility, fieldIndices: fields.map { $0.rawValue })
        }
        else {
            setErrorFormat(facility: facility, fieldIndices: nil)
        }
    }
    
    public func setErrorFormat (fields:[LKFErrorField]) {
        setErrorFormat(facility: 0, fields: fields)
    }
    
    public override func getOutput() -> [String] {
   
        var outputStrings = [String]()
        
        if context.ptr == nil {
            return ["context is null"]
        }
        
        LibLKF.lkf_setErrorFormat(context.ptr!, 7, 0, nil)
        if let errorFormatFields = self.errorFormatFields {
            for eff in errorFormatFields {
                if let fields = eff.value {
                   // let unsafe = UnsafePointer<UInt32>(fields)
                                       
                    _ = fields.withUnsafeBufferPointer { unsafe in
                        LibLKF.lkf_setErrorFormat(context.ptr!, eff.key, UInt32(fields.count), unsafe.baseAddress)
                    }
                    if facility == 0 {
                        facility = eff.key
                    }
                }
                else {
                    LibLKF.lkf_setErrorFormat(context.ptr!, eff.key, 0, nil)
                }
            
            }
        }
        
        let count = LibLKF.lkf_setErrorFilter(context.ptr!, errorTypes)
   
        if count == LKF_OUTOFMEMORY_UINTERROR {
            return []
        }
        
        let lineBuffer = UnsafeMutablePointer<CChar>.allocate(capacity:1024)

        if withHeadline {
            LibLKF.lkf_getSatzartErrorHeadline(context.ptr!, facility, 1024, lineBuffer)
            outputStrings.append(String(cString:lineBuffer))
        }
        
        for i in 0..<count {
            LibLKF.lkf_getSatzartError(context.ptr!, i, 1024, lineBuffer)
            outputStrings.append(String(cString:lineBuffer))
        }
        lineBuffer.deallocate()
        return outputStrings
    }
    
    public func getOutput(linePrefix: String) -> [String] {
        return getOutput().map { "\(linePrefix)\($0)" }
    }

    public override var defaultfileName : String {
        return "\(context.KANR)j001.e\(context.model%100)"
    }
}

public class LKFOutputWarningFile : LKFOutputErrorFile {
    
    public override init (context: LKFContext, withHeadline: Bool = true) {
        super.init(context: context, withHeadline: withHeadline)
        errorTypes = 65280
    }
    
    public override var defaultfileName : String {
        return "\(context.KANR)j001.w\(context.model%100)"
    }
}

public class LKFOutputInfoFile : LKFOutputErrorFile {
    
    public override init (context: LKFContext, withHeadline: Bool = true) {
        super.init(context: context, withHeadline: withHeadline)
        errorTypes = 1048576
    }
    
    public override var defaultfileName : String {
        return "\(context.KANR)j001.h\(context.model%100)"
    }
}
