//
//  MatchDescriptor.swift
//  PadelClub
//
//  Created by Razmig Sarkissian on 02/04/2024.
//

import Foundation

class MatchDescriptor: ObservableObject {
    @Published var matchFormat: MatchFormat
    @Published var setDescriptors: [SetDescriptor]
    var court: Int = 1
    var title: String = "Titre du match"
    var teamLabelOne: String = ""
    var teamLabelTwo: String = ""
    var startDate: Date = Date()
    var match: Match?

    init(match: Match? = nil) {
        self.match = match
        if let groupStage = match?.groupStageObject {
            self.matchFormat = groupStage.matchFormat
            self.setDescriptors = [SetDescriptor(setFormat: groupStage.matchFormat.setFormat)]
        } else {
            let format = match?.matchFormat ?? match?.currentTournament()?.matchFormat ?? .defaultFormatForMatchType(.groupStage)
            self.matchFormat = format
            self.setDescriptors = [SetDescriptor(setFormat: format.setFormat)]
        }
        let teamOne = match?.team(.one)
        let teamTwo = match?.team(.two)
        self.teamLabelOne = teamOne?.teamLabel(.wide, twoLines: true) ?? ""
        self.teamLabelTwo = teamTwo?.teamLabel(.wide, twoLines: true) ?? ""
        
        if let match, let scoresTeamOne = match.teamScore(ofTeam: teamOne)?.score, let scoresTeamTwo = match.teamScore(ofTeam: teamTwo)?.score {
         
            self.setDescriptors = combineArraysIntoTuples(scoresTeamOne.components(separatedBy: ","), scoresTeamTwo.components(separatedBy: ",")).map({ (a:String?, b:String?) in
                SetDescriptor(valueTeamOne: a != nil ? Int(a!) : nil, valueTeamTwo: b != nil ? Int(b!) : nil, setFormat: match.matchFormat.setFormat)
            })
        }
    }

    var teamOneScores: [String] {
        setDescriptors.compactMap { $0.valueTeamOne }.map { "\($0)" }
    }

    var teamTwoScores: [String] {
        setDescriptors.compactMap { $0.valueTeamTwo }.map { "\($0)" }
    }
    
    var scoreTeamOne: Int { setDescriptors.compactMap { $0.winner }.filter { $0 == .one }.count }
    var scoreTeamTwo: Int { setDescriptors.compactMap { $0.winner }.filter { $0 == .two }.count }

    var hasEnded: Bool {
        return matchFormat.hasEnded(scoreTeamOne: scoreTeamOne, scoreTeamTwo: scoreTeamTwo)
    }
    
    func addNewSet() {
        if hasEnded == false {
            setDescriptors.append(SetDescriptor(setFormat: matchFormat.newSetFormat(setCount: setDescriptors.count)))
        }
    }
    
    var winner: TeamPosition {
        matchFormat.winner(scoreTeamOne: scoreTeamOne, scoreTeamTwo: scoreTeamTwo)
    }
    
    var winnerLabel: String {
        if winner == .one {
            return teamLabelOne
        } else {
            return teamLabelTwo
        }
    }
}

fileprivate func combineArraysIntoTuples(_ array1: [String], _ array2: [String]) -> [(String?, String?)] {
    // Zip the two arrays together and map them to tuples of optional strings
    let combined = zip(array1, array2).map { (element1, element2) in
        return (element1, element2)
    }
    
    // If one array is longer than the other, append the remaining elements
    let remainingElements: [(String?, String?)]
    if array1.count > array2.count {
        let remaining = Array(array1[array2.count...]).map { (element) in
            return (element, nil as String?)
        }
        remainingElements = remaining
    } else if array2.count > array1.count {
        let remaining = Array(array2[array1.count...]).map { (element) in
            return (nil as String?, element)
        }
        remainingElements = remaining
    } else {
        remainingElements = []
    }
    
    // Concatenate the two arrays
    return combined + remainingElements
}
