//
//  LKFScoringDetailsGroup.swift
//  LKF
//
//  Created by Alexander Holzer on 26.02.22.
//  Copyright © 2022 Alexander Holzer. All rights reserved.
//

import Foundation
@_implementationOnly import LibLKF

public enum LKFScoringDetailsGroupPositions : Int {
    case group = 0
    case knt = 1
    case scges = 2
    case ldfplk = 3
    case ldfptk = 4
    case count = 5
    case melzu = 6
    case melzu_direct = 7
    case sculk = 8
    case scutk = 9
    case vdzu = 10
    case melzu_voll = 11
    case melzu_reduziert = 12
    case vdu = 13
    case vdo = 14
    case vdmw = 15
    case diagmel = 16
}

public class LKFScoringDetailsGroup {
    public let parts : [String]
    public let inactive : Bool
    public let subgruppeParts : [String]?
    public let subgruppeIndex: Int32?
    public let mainGroup: Bool
    public var comments : [String]?
    
    init (aufenthalt:LKFAufenthalt, parts:[String], mainGroupIndex:Int) {
        let lineBuffer = UnsafeMutablePointer<CChar>.allocate(capacity:2048)
        let aufenthaltPtr = aufenthalt.ptr        
        self.parts = parts
        self.inactive = (Int(parts[0]) ?? 1) != 0
        if parts.count > 3 {
            self.subgruppeIndex = Int32(parts[3])
            if let subgruppeIndex = self.subgruppeIndex {
                self.mainGroup = mainGroupIndex == Int(subgruppeIndex)
                LibLKF.lkf_scoringdetails_getSubgruppe (aufenthaltPtr,  subgruppeIndex, lineBuffer, 2048)
                let str = String.utf8String(cString: lineBuffer)
                let subgruppeParts = str.components(separatedBy: "|")
                self.subgruppeParts = subgruppeParts
            }
            else {
                self.mainGroup = false
                self.subgruppeParts = nil
            }
            self.comments = nil
        }
        else {
            self.mainGroup = false
            self.subgruppeIndex = nil
            self.subgruppeParts = nil
            self.comments = nil
        }
        lineBuffer.deallocate()
    }

    static public func stringValue (for field: LKFScoringDetailsGroupPositions, in subgruppeParts: [String]) -> String {
        let index = field.rawValue
        if subgruppeParts.count > index {
            return subgruppeParts[index]
        }
        return ""
    }
    
    public func stringValue (for field: LKFScoringDetailsGroupPositions) -> String {
        guard let subgruppeParts else {
            return ""
        }
        return LKFScoringDetailsGroup.stringValue(for: field, in: subgruppeParts)
    }
    
    public func intValue (for field: LKFScoringDetailsGroupPositions) -> Int? {
        let index = field.rawValue
        if let subgruppeParts = subgruppeParts, subgruppeParts.count > index {
            return Int(subgruppeParts[index])
        }
        return nil
    }
    
    public func intValueOr0 (for field: LKFScoringDetailsGroupPositions) -> Int {
        let index = field.rawValue
        if let subgruppeParts = subgruppeParts, subgruppeParts.count > index {
            return Int(subgruppeParts[index]) ?? 0
        }
        return 0
    }

    public func doubleValue (for field: LKFScoringDetailsGroupPositions) -> Double? {
        let index = field.rawValue
        if let subgruppeParts = subgruppeParts, subgruppeParts.count > index {
            return Double(subgruppeParts[index])
        }
        return nil
    }

    public func stringValue (forDouble field: LKFScoringDetailsGroupPositions, defaultValue: String = "0") -> String {
        if let value = doubleValue(for: field) {
            return "\(value)"
        }
        return defaultValue
    }
    
    public func stringValue (forInt field: LKFScoringDetailsGroupPositions, defaultValue: String = "0") -> String {
        if let value = doubleValue(for: field) {
            return "\(value)"
        }
        return defaultValue
    }
    
    public var SCGES : Int? {
        return intValue(for: .scges)
    }
    
    public var LDFPLK : Int? {
        return intValue(for: .ldfplk)
    }
    
    public var LDFPTK : Int? {
        return intValue(for: .ldfptk)
    }
    
    public var SCUTK : Int? {
        return intValue(for: .scutk)
    }
    
    public var SCULK: Int? {
        return intValue(for: .sculk)
    }
    
    public var VDZU : Int? {
        return intValue(for: .vdzu)
    }
    
    public var Count: Int? {
        return intValue(for: .count)
    }
    
    public var VDU: Int? {
        return intValue(for: .vdu)
    }
    
    public var VDO: Int? {
        return intValue(for: .vdo)

    }
    
    public var VDMW: Double? {
        return doubleValue(for: .vdmw)
    }
    
    public var VD: String {
        return "\(stringValue(forInt: .vdu)) < \(stringValue(forDouble: .vdmw)) < \(stringValue(forInt: .vdo))"
    }
    
    public var MELZU: Int? {
        return intValue(for: .melzu)
    }
    
    public var GROUP : String {
        return stringValue(for: .group)
    }
    
    public var KNT : String {
        return stringValue(for: .knt)
    }
    
    public var grouped : Bool {
        if let ival = Int(parts[0]) {
            return ival == 2
        }
        return false
    }

    public var active : Bool {
        if let ival = Int(parts[0]) {
            return ival == 0
        }
        return false
    }
    
    public var group : String {
        if parts.count > 1 {
            return parts[1]
        }
        return ""
    }
    public var inactiveString : String {
        if let ival = Int(parts[0]) {
            switch (ival) {
            case 0:
                return "ACTIVE"
            case 1:
                return "INACTIVE"
            case 2:
                return "GROUP"
            default:
                return "UNKNOWN"
            }
        }
        return "UNKNOWN"
    }
    
    public var traceIdent: String {
        return ""
    }
    
    public var traceLine : String {
        if !active {
            return "\(traceIdent): \(inactiveString)"
        }
        else {
            return "\(traceIdent): \(group)"
        }
    }
    
    public var traceLines : [String] {
        if !active {
            return [traceLine]
        }
        else {
            var arr = [String]()
            
            arr.append(traceLine)
            if let subgruppeParts = subgruppeParts {
                arr.append(subgruppeParts.joined(separator: "|"))
            }
            if let comments = comments {
                for c in comments {
                    arr.append(c)
                }
            }
            return arr
        }
    }
    
    public func allParts() -> String {
        return parts.joined (separator:"|")
    }
    
    public var index : UInt32 {
        return 0
    }
}
