//
//  SwiftParser.swift
//  Padel Tournament
//
//  Created by Razmig Sarkissian on 01/09/2023.
//

import Foundation

typealias LineIterator = AsyncLineSequence<URL.AsyncBytes>.AsyncIterator
struct Line: Identifiable {
    let id: UUID = UUID()
    let date: Date
    let source: URL
    let lineNumber: Int
    let rawValue: String
    let data: [String?]

//    func updatePlayer(player: Player) {
//        player.clubName = data[11]
//        player.ligue = data[9]
//        player.country = data[4]
//        player.license = data[5]
//        player.inscriptionRank = rank
//        player.currentRank = rank
//        player.tournamentCount = Int16(tournamentCount)
//        player.points = points ?? 0
//        player.codeClub = data[10]
//        player.assimilation = assimilation
//    }
    
    var points: Double? {
        if let pointsValue {
            return Double(pointsValue.replacingOccurrences(of: ",", with: "."))
        }
        return nil
    }
    
    var pointsValue: String? {
        data[6] ?? nil
    }
    
    var tournamentCountValue: String? {
        data[8] ?? nil
    }
    
    var tournamentCount: Int64 {
        if let tournamentCountValue {
            return Int64(tournamentCountValue) ?? 0
        }
        return 0
    }
    
    var rankValue: String? {
        data[1] ?? nil
    }
    
    var rank: Int {
        if let rankValue {
            return Int(rankValue) ?? 0
        }
        return 0
    }
    
    var assimilation: String? {
        data[7]
    }
}

struct CSVParser: AsyncSequence, AsyncIteratorProtocol {
    typealias Element = Line
      
    private let url: URL
    private var lineIterator: LineIterator
    private let seperator: Character
    private let quoteCharacter: Character = "\""
    private var lineNumber = 0
    private let date: Date
    let maleData: Bool

    init(url: URL, seperator: Character = ";") {
        self.date = url.dateFromPath
        self.url = url
        self.seperator = seperator
        self.lineIterator = url.lines.makeAsyncIterator()
        self.maleData = url.path().contains(SourceFile.messieurs.rawValue)
    }
    
    mutating func last() async throws -> Line? {
        var lastString: String?
        var currentString: String?
        var isOver: Bool = false
        while isOver == false {
            lastString = currentString
            currentString = try await lineIterator.next()
            if currentString == nil {
                isOver = true
            }
        }

        if let lastString {
            return Line(
                date: date,
                source: url,
                lineNumber: lineNumber,
                rawValue: lastString,
                data: split(line: lastString))
        }
        return nil
    }
    
    mutating func next() async throws -> Line? {
        if let string = try await lineIterator.next() {
            defer { lineNumber += 1 }
            return Line(
                date: date,
                source: url,
                lineNumber: lineNumber,
                rawValue: string,
                data: split(line: string)
            )
        }
          
        return nil
    }
    
    func makeAsyncIterator() -> CSVParser {
        return self
    }
      
    private func split(line: String) -> [String?] {
        var data = [String?]()
        var inQuote = false
        var currentString = ""
            
        for character in line {
            switch character {
            case quoteCharacter:
                inQuote = !inQuote
                continue
                      
            case seperator:
                if !inQuote {
                    data.append(currentString.isEmpty ? nil : currentString)
                    currentString = ""
                    continue
                }

            default:
                break
            }
                  
            currentString.append(character)
        }
            
        data.append(currentString.isEmpty ? nil : currentString)
            
        return data
    }
}
