//
//  lkfc2020Tests.swift
//  lkfcTests
//
//  Created by Alexander Holzer on 09.07.19.
//  Copyright © 2019 Alexander Holzer. All rights reserved.
//

import XCTest
@testable import lkfc

class lkfc2020Tests: XCTestCase {
    
    func createContextWith (model: UInt32, lines : [String]) throws -> LKFContext {
        return try lkfcTests.createContextWith(model:model, lines:lines)
    }
    
    func createContextWith (model: UInt32, year: Int32, lines : [String]) throws -> LKFContext {
        return try lkfcTests.createContextWith(model:model, year: year, lines:lines)
    }

    
    func resultForContext (context: LKFContext) -> String {
        return lkfcTests.resultForContext (context: context)
    }
    
    func combine (_ first:[String], _ second:[String]) -> [String] {
        return lkfcTests.combine(first, second)
    }
    
    func expectErrorCount (context: LKFContext, code:String) -> Int {
        let err = context.errorsWith(code: code)
        return err?.count ?? 0
    }
    
    func expectError (context: LKFContext, code:String) -> Bool {
        return expectErrorCount(context: context, code: code) == 1
    }

    
    static var fall_geschl = [
        "X01|K714|1234||20190621|1200|S|19360601|80|X|AT|AT|1010|90101|A|P||||E|20190621|1200|11|J|0",
        "X02|K714|1234||20190621|01|11111100|20190621||J||||||N|80|",
                "X03|K714|1234||20190621|I51.9|H|D||",
        "X03|K714|1234||20190621|R53|Z|D||",
        "X04|K714|1234||20190621|BG020||J|0001|20190621|2024|18111600|"]
    
    func testGESCHL () throws {
        var context = try createContextWith(model:2019, lines: lkfc2020Tests.fall_geschl)
        XCTAssert (context.lastError == nil, "couldn't not execute case" + context.lastError!.message)
        var res = resultForContext(context: context)
        var errors = context.errorsWith (code:"EX06") // Geschlecht falsch
        XCTAssert (errors != nil, "missing error EX06")

        context = try createContextWith(model:2020, lines: lkfc2020Tests.fall_geschl)
        XCTAssert (context.lastError == nil, "couldn't not execute case" + context.lastError!.message)
        res = resultForContext(context: context)
        errors = context.errorsWith (code:"EX06") // Geschlecht falsch (X ok in 2020)
        XCTAssert (errors == nil, "invalid error EX06")

        XCTAssert (res.compare("X05|K714|1234||20190621|HDG06.04|A|||36|30|||||66") == ComparisonResult.orderedSame, "result different")
    }
    
    static var fall_diff15 = [
    "X01|K201|123||20190109|0615|S|19920501|25|W|AT|AT|8753|62007|K|P||||E|20190109|1800|15|J|2",
    "X02|K201|123||20190109|001|11211100|20190109|0615||20190109|1800||||N|25|",
    "X03|K201|123||20190109|I83.9|H|D||",
    "X04|K201|123||20190109|AP520||J|1|20190109|0740|16711100||",
    "X04|K201|123||20190109|EK050|L|J|1|20190109|0802|16919500||"
    ]
    
    func testFallFactor15 () throws {
        var context = try createContextWith(model:2019, lines: lkfc2020Tests.fall_diff15)
        XCTAssert (context.lastError == nil, "couldn't not execute case" + context.lastError!.message)
        var res = resultForContext(context: context)
        XCTAssert (res.compare("X05|K201|123||20190109|MEL09.03|B|||1399|884|||||2283") == ComparisonResult.orderedSame, "result different")

        
        context = try createContextWith(model:2020, lines: lkfc2020Tests.fall_diff15)
        XCTAssert (context.lastError == nil, "couldn't not execute case" + context.lastError!.message)
        res = resultForContext(context: context)
        XCTAssert (res.compare("X05|K201|123||20190109|MEL09.03|B|||1399|789|||||2188") == ComparisonResult.orderedSame, "result different")
    }

    static var fall_bdgr0tkl = [
        "X01|K201|123||20190109|0615|S|19920501|25|W|AT|AT|8753|62007|K|P||||E|20190109|1800|15|J|2",
        "X02|K201|123||20190109|001|11211100|20190109|0615||20190109|1800||||N|25|",
        "X03|K201|123||20190109|J95.0|H|D||",
        "X04|K201|123||20190109|AK020||J|1|20190109|0740|16711100||"
    ]
    
    static var fall_add1 = ["X04|K201|123||20190109|EK050|L|J|1|20190109|0802|16919500||"]
    
    static var fall_addX06 = ["X06|K201|123||20190109|001:AK020|WX3P|BDGR0 accepted"]
    
    func testFallBDGR0TKL () throws {
        var context = try createContextWith(model:2019, lines: lkfc2020Tests.fall_bdgr0tkl)
        XCTAssert (context.lastError == nil, "couldn't not execute case" + context.lastError!.message)
        var res = resultForContext(context: context)
        XCTAssert (res.compare("X05|K201|123||20190109|MEL01.08|B|||438|30|||||468") == ComparisonResult.orderedSame, "result different")
        
        context = try createContextWith(model:2020, lines: lkfc2020Tests.fall_bdgr0tkl)
        XCTAssert (context.lastError == nil, "couldn't not execute case" + context.lastError!.message)
        res = resultForContext(context: context)
        XCTAssert (res.compare("X05|K201|123||20190109|MEL01.08|B|||438|30|||||468") == ComparisonResult.orderedSame, "result different")

        context = try createContextWith(model:2020, lines: combine (lkfc2020Tests.fall_bdgr0tkl, lkfc2020Tests.fall_addX06))
        XCTAssert (context.lastError == nil, "couldn't not execute case" + context.lastError!.message)
        res = resultForContext(context: context)
        XCTAssert (res.compare("X05|K201|123||20190109|MEL01.08|B|||946|519|||||1465") == ComparisonResult.orderedSame, "result different")

        
        let withEK050 = combine(lkfc2020Tests.fall_bdgr0tkl, lkfc2020Tests.fall_add1)
        
        context = try createContextWith(model:2019, lines: withEK050)
        XCTAssert (context.lastError == nil, "couldn't not execute case" + context.lastError!.message)
        res = resultForContext(context: context)
        XCTAssert (res.compare("X05|K201|123||20190109|MEL09.03|B|||1399|884|||438||2721") == ComparisonResult.orderedSame, "result different")
        
        context = try createContextWith(model:2020, lines: withEK050)
        XCTAssert (context.lastError == nil, "couldn't not execute case" + context.lastError!.message)
        res = resultForContext(context: context)
        XCTAssert (res.compare("X05|K201|123||20190109|MEL09.03|B|||1399|789|||438||2626") == ComparisonResult.orderedSame, "result different")

        context = try createContextWith(model:2020, lines: combine (withEK050, lkfc2020Tests.fall_add1))
        XCTAssert (context.lastError == nil, "couldn't not execute case" + context.lastError!.message)
        res = resultForContext(context: context)
        XCTAssert (res.compare("X05|K201|123||20190109|MEL09.03|B|||1399|789|||1118||3306") == ComparisonResult.orderedSame, "result different")

    }

    
    static var fall_geburt = [
    "X01|K955|111||20200115|1525|S|19890301|20|W|AT|AT|1190|91901|A|P||||E|20200115|1417|11|J|0",
    "X02|K955|111||20200115|001|11331100|20200115|1525|||||||N|20|",
    "X03|K955|111||20200115|O80.0|H|||",
    "X04|K955|111||20200115|JN020||J|1|20200115|2333|11331100||",
    "X05|K955|111||20200115|MEL13.09|C|668|2369|||||||3037"
    ]
    
    static var fall_geburt_zd = ["X03|K955|111||20200115|301.32|Z|||"]

    static var fall_geburt_zd_doppelt =
        ["X03|K955|111||20200115|301.32|Z|||",
         "X03|K955|111||20200115|301.32|Z|||"]

    
    static var fall_geburt_zd_diff = ["X03|K955|111||20200115|301.32|Z|||",
                                 "X03|K955|111||20200115|301.33|Z|||"]

    
    
    func testFallGeburt () throws {
        var context = try createContextWith(model:2019, lines: lkfc2020Tests.fall_geburt)
        XCTAssert (context.lastError == nil, "couldn't not execute case" + context.lastError!.message)
        var res = resultForContext(context: context)
        XCTAssert (!expectError (context: context, code:"WX54"), "WX54 returned with model 2019")
        XCTAssert (res.compare("X05|K955|111||20200115|MEL13.09|C|||668|2369|||||3037") == ComparisonResult.orderedSame, "result different")
        
        
        context = try createContextWith(model:2020, lines: lkfc2020Tests.fall_geburt)
        XCTAssert (context.lastError == nil, "couldn't not execute case" + context.lastError!.message)
        res = resultForContext(context: context)
        XCTAssert (expectError (context: context, code:"EX4U"), "EX4U not returned with model 2020")
        // WX54 -> EX4U
 
        context = try createContextWith(model:2020, lines: combine (lkfc2020Tests.fall_geburt, lkfc2020Tests.fall_geburt_zd))
        XCTAssert (context.lastError == nil, "couldn't not execute case" + context.lastError!.message)
        res = resultForContext(context: context)
        XCTAssert (!expectError (context: context, code:"EX4U"), "EX4U returned although 301.32")
        // TODO: differenz zu Modell 2019
        XCTAssert (res.compare("X05|K955|111||20200115|MEL13.09|C|||668|1015|||||1683") == ComparisonResult.orderedSame, "result different")

        context = try createContextWith(model:2020, lines: combine (lkfc2020Tests.fall_geburt, lkfc2020Tests.fall_geburt_zd_diff))
        XCTAssert (context.lastError == nil, "couldn't not execute case" + context.lastError!.message)
        res = resultForContext(context: context)
        XCTAssert (expectError (context: context, code:"EX4V"), "EX4V not returned")

        context = try createContextWith(model:2020, lines: combine (lkfc2020Tests.fall_geburt, lkfc2020Tests.fall_geburt_zd_doppelt))
        XCTAssert (context.lastError == nil, "couldn't not execute case" + context.lastError!.message)
        res = resultForContext(context: context)
        XCTAssert (!expectError (context: context, code:"EX4V"), "EX4V returned")
        // TODO: differenz zu Modell 2019
        XCTAssert (res.compare("X05|K955|111||20200115|MEL13.09|C|||668|1015|||||1683") == ComparisonResult.orderedSame, "result different")

    }
    
    static var fall_sharpDiagSP2ZD = [
        "X01|K201|234||20170205|1749|I|20060601|10|M|AT|AT|9363|20518|||||||||56|J|2",
        "X02|K201|234||20170205|001|16221100|20170205|1749|J||||||N|10|",
        "X03|K201|234||20170205|S61.0|H|D||",
        "X03|K201|234||20170205|929.9|Z|D||",
        "X03|K201|234||20170205|Z00.0|Z|D||",
        "X04|K201|234||20170205|AJ010|L|J|1|20170205|1800|16221100||",
        "X04|K201|234||20170205|QZ760||J|1|20170205|1749|16221100||"
    ]
    
    static var fall_aj040 = [
        "X01|K201|345||20170301|1749|I|20060701|10|M|AT|AT|9363|20518|||||||||56|J|2",
        "X02|K201|345||20170301|001|16221100|20170301|1749|J||||||N|10|",
        "X03|K201|345||20170301|S61.0|Z|D||",
        "X03|K201|345||20170301|929.9|Z|D||",
        "X03|K201|345||20170301|Z00.0|H|D||",
        "X04|K201|345||20170301|AJ040||J|1|20170301|1800|16221100||",
        "X04|K201|345||20170301|QZ760||J|1|20170301|1749|16221100||"
    ]
    
    static var fall_aj040_addX06 = ["X06|K201|345||20170301|001:AJ040|WX3P|BDGR0 accepted"]
    
    func testAmbtkl_2020() throws {
        var context = try createContextWith (model: 2020, year: 2017, lines: lkfc2020Tests.fall_sharpDiagSP2ZD)
        var s = resultForContext(context: context)
        XCTAssert (s.compare("X05|K201|234||20170205|MEL02.01|A|||1079|721|||||1800") == ComparisonResult.orderedSame, "result different")
        context = try createContextWith (model: 2020, year: 2017, lines:  lkfc2020Tests.fall_aj040)
        s = resultForContext(context: context)
        XCTAssert (s.compare("X05|K201|345||20170301|APG09.11|A|48|35|||||||83") == ComparisonResult.orderedSame, "result different")
        XCTAssert(context.errorsWith(code: "WX3P") != nil, "WX3P missing")
        context = try createContextWith (model: 2020, year: 2017, lines: combine (lkfc2020Tests.fall_aj040, lkfc2020Tests.fall_aj040_addX06))
        s = resultForContext(context: context)
        XCTAssert (s.compare("X05|K201|345||20170301|APG09.11|A|48|35|||||||83") == ComparisonResult.orderedSame, "result different")
    }
    
    static var fall_tkl_2020 = [
        "X01|K714|1234||20190102|1200|S|19360601|80|M|AT|AT|1010|90101|A|P||||E|20190102|1200|11|J|0",
        "X02|K714|1234||20190102|01|11111100|20190102||J||||||N|80|",
        "X03|K714|1234||20190102|I51.9|H|D||",
        "X04|K714|1234||20190102|QZ050||J|1|20190102|0120|17821100||"]
    
    
    func testTKL0Tage_2020 () throws {
        /* TODO Modell 2020: modell 2019 vs modell 2020 */
        let context = try createContextWith (model: 2020, year: 2019, lines: lkfc2020Tests.fall_tkl_2020)
        let s = resultForContext(context: context)
        XCTAssert (s.compare("X05|K714|1234||20190102|MEL14.22|B|||1106|702|||||1808") == ComparisonResult.orderedSame, "result different")
    }
    
    static var fall_xcxb = [
        "X01|K201|123||20190109|0615|S|20030602|25|W|AT|AT|8753|62007|K|P||||E|20190113|1800|15|J|2",
        "X02|K201|123||20190109|001|11211100|20190109|0615||20190109|1800||||N|25|",
        "X03|K201|123||20190109|C71.9|H|D||",
        "X04|K201|123||20190109|XC112||J|1|20190109|0740|16711100||",
        "X04|K201|123||20190109|XB110||J|1|20190109|0740|16711100||"
    ]
    
       // static var fall_aj040_addX06 = ["X06|K201|2017700355||20170108|001:AJ040|WX3P|BDGR0 accepted"]

    static var fall_xcxb_x06 = [
        "X06|K201|123||20190109|XB110XC112|WX54|XBXC"
    ]
    
    func testXCXB_2020 () throws {
        var context = try createContextWith (model: 2020, year: 2019, lines: lkfc2020Tests.fall_xcxb)
        var s = resultForContext(context: context)
        XCTAssert (expectError (context: context, code:"WX54"), "WX54 missing")
        XCTAssert (s.compare("X05|K201|123||20190109|MEL22.04|A|||2688|1968|||||4656") == ComparisonResult.orderedSame, "result different")
        context = try createContextWith (model: 2020, year: 2019, lines: combine(lkfc2020Tests.fall_xcxb, lkfc2020Tests.fall_xcxb_x06))
        s = resultForContext(context: context)
        XCTAssert (!expectError (context: context, code:"WX54"), "WX54 although accepted")
        XCTAssert (s.compare("X05|K201|123||20190109|MEL22.04|A|||2688|1968|||325||4981") == ComparisonResult.orderedSame, "result different")
    }
    
    static var fall_lh021 = [
        "X01|K901|123||20190109|0615|S|20030603|25|W|AT|AT|8753|62007|A|P||||E|20190113|1800|15|J|2",
        "X02|K901|123||20190109|001|11211100|20190109|0615||20190113|1800||||N|25|",
        "X03|K901|123||20190109|M48.0|H|D||",
//        "X04|K901|123||20190109|LH021||J|1|20190109|0740|16711100||"
        "X04|K901|123||20190109|LH021||J|1|20190109|0740||K914|"
    ]
    
    static var fall_lh021_l01 : [String] = ["L01|2019|K914||M|06|"]
    
    func test_lh021() throws {
        
        var context = try createContextWith (model: 2019, year: 2019, lines: lkfc2020Tests.fall_lh021)
        var s = resultForContext(context: context)
        XCTAssert (!expectError (context: context, code:"WX3Q"), "WX3Q not expected")
        XCTAssert (s.compare("X05|K901|123||20190109|MEL01.17|C|1971|2848|||||||4819") == ComparisonResult.orderedSame, "result different")
        context = try createContextWith (model: 2020, year: 2019, lines: lkfc2020Tests.fall_lh021)
        s = resultForContext(context: context)
        XCTAssert (expectError (context: context, code:"WX3Q"), "WX3Q missing")
        XCTAssert (s.compare("X05|K901|123||20190109|HDG01.32|C|153|1694|||||||1847") == ComparisonResult.orderedSame, "result different")
 
        context = try createContextWith (model: 2020, year: 2019, lines: combine(lkfc2020Tests.fall_lh021, lkfc2020Tests.fall_lh021_l01))
        s = resultForContext(context: context)
        XCTAssert (!expectError (context: context, code:"WX3Q"), "WX3Q not expected")
        XCTAssert (s.compare("X05|K901|123||20190109|MEL01.17|C|1971|2848|||||||4819") == ComparisonResult.orderedSame, "result different")

    }
    
    static var fall_zn800 = [
        "X01|K901|123||20190109|0615|S|20030603|25|W|AT|AT|8753|62007|A|P||||S|20190113|1800|15|J|2",
        "X02|K901|123||20190109|001|11211100|20190109|0615||20190113|1800||||N|25|",
        "X03|K901|123||20190109|M48.0|H|D||",
        "X04|K901|123||20190109|ZN800||J|1|20190211|0740||K914|"
    ]

    func test_zn800() throws {
        
        var context = try createContextWith (model: 2018, year: 2019, lines: lkfc2020Tests.fall_zn800)
        var s = resultForContext(context: context)
        XCTAssert (expectError (context: context, code:"EX29"), "EX29 missing")
        context = try createContextWith (model: 2019, year: 2019, lines: lkfc2020Tests.fall_zn800)
        s = resultForContext(context: context)
        XCTAssert (!expectError (context: context, code:"EX29"), "EX29 not expected")
        XCTAssert (s.compare("X05|K901|123||20190109|HDG01.32|C|153|1882|||||||2035") == ComparisonResult.orderedSame, "result different")
        
    }
    
    static var fall_accept_melabt = [
        "X01|K201|345||20170301|1749|I|20060701|10|M|AT|AT|9363|20518|||||||||56|J|2",
        "X02|K201|345||20170301|001|16111100|20170301|1749|J||||||N|10|",
        "X02|K201|345||20170301|002|16221100|20170301|1822|J||||||N|10|",
        "X03|K201|345||20170301|S61.0|Z|D||",
        "X03|K201|345||20170301|929.9|Z|D||",
        "X03|K201|345||20170301|Z00.0|H|D||",
        "X04|K201|345||20170301|AJ040||J|1|20170301|1822|16221100||",
        "X04|K201|345||20170301|QZ760||J|1|20170301|1722|16221100||"
    ]
    
    static var fall_accept_emlabtX05 = [
        "X06|K201|345||20170301|002:AJ040|WX3P|BDGR0 accepted"
    ]
    
    func test_accept_melabt() throws {
        
        var context = try createContextWith (model: 2020, year: 2017, lines: lkfc2020Tests.fall_accept_melabt)
        var s = resultForContext(context: context)
        XCTAssert (s.compare("X05|K201|345||20170301|APG09.11|A|48|35|||||||83") == ComparisonResult.orderedSame, "result different")
        XCTAssert (expectError (context: context, code:"WX3P"), "WX3P missing")

        context = try createContextWith (model: 2020, year: 2017, lines: lkfcTests.combine (lkfc2020Tests.fall_accept_melabt, lkfc2020Tests.fall_accept_emlabtX05))
        s = resultForContext(context: context)
        XCTAssert (s.compare("X05|K201|345||20170301|APG09.11|A|48|35|||||||83") == ComparisonResult.orderedSame, "result different")
        XCTAssert (!expectError (context: context, code:"WX3P"), "WX3P not expected")
    }
    
    static var fall_ed010 = [
        "X01|K201|345||20170301|1749|I|20060701|10|M|AT|AT|9363|20518|||||||||56|J|2",
        "X02|K201|345||20170301|001|16111100|20170301|1749|J||||||N|10|",
        "X02|K201|345||20170301|002|16221100|20170301|1822|J||||||N|10|",
  //      "X03|K201|345||20170301|B97.7|H|D||",
        "X03|K201|345||20170301|R94.4|H|D||",
        "X03|K201|345||20170301|M96.86|H|D||",
        "X04|K201|345||20170301|ED010||J|1|20170301|1822|16221100||"
    ]

    func test_accept_ed010() throws {
        
        let context = try createContextWith (model: 2020, year: 2017, lines: lkfc2020Tests.fall_ed010)
        let s = resultForContext(context: context)
        XCTAssert (s.compare("X05|K201|345||20170301|HDG14.04|C|||97|924|||||1021") == ComparisonResult.orderedSame, "result different")
    }

    /*
    static var fall_exp = [
    "X01|K612|123||20190620|0710|S|19580423|60|W|AT|AT|8403|61021|K|P||||E|20190620|0943|50|J|0",
    "X02|K612|123||20190620|001|14418500|20190620|0710|||||||N|60|",
    "X03|K612|123||20190620|H26.2|H|||",
    "X03|K612|123||20190620|H25.0|Z|||",
    "X03|K612|123||20190620|H43.8|Z|||",
    "X03|K612|123||20190620|H53.0|Z|||"
    ]

    func test_exp () {
        
        let context = try createContextWith (model: 2019, year: 2019, lines: lkfc2020Tests.fall_exp)
        let s = resultForContext(context: context)
        print(s)
    }
    */

    
    override func setUp() {
        // Put setup code here. This method is called before the invocation of each test method in the class.
    }

    override func tearDown() {
        // Put teardown code here. This method is called after the invocation of each test method in the class.
    }
}
