package de.jeyp91.tippliga;

import com.google.common.io.Resources;
import de.jeyp91.apifootball.APIFootballConnector;
import de.jeyp91.apifootball.APIFootballMatch;
import de.jeyp91.gists.GistProvider;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;

import java.io.IOException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;

public class TLWMatchesCreatorFootball extends TLWMatchesCreatorBase {

    int season;
    int league;
    int numberOfMatchdays;
    int matchesPerMatchday;
    int ko;
    int nextMatchNo = 1;
    JSONArray matchdayConfig;

    public TLWMatchesCreatorFootball(int season, int league, String configFileName) {

        super();

        this.season = season;
        this.league = league;
        this.conn = APIFootballConnector.getAPIFootballConnectorInstance(season - 1);

        GistProvider prov = GistProvider.getInstance();
        String jsonConfig = prov.getTippligaConfig(2021, configFileName);

        try {
            JSONParser jsonParser = new JSONParser();
            //Read JSON file
            JSONObject config = (JSONObject) jsonParser.parse(jsonConfig);
            this.numberOfMatchdays = ((Long) config.get("numberOfMatchdays")).intValue();
            this.matchdayConfig = (JSONArray) config.get("matchdayConfig");
            this.ko = ((Long) config.get("ko")).intValue();

        } catch (ParseException e) {
            e.printStackTrace();
        }

        this.publicateMatchObjects();
    }

    private void publicateMatchObjects() {

        for(int i = 0; i < this.matchdayConfig.size(); i++) {
            int TLWMatchday = ((Long) ((JSONObject) this.matchdayConfig.get(i)).get("TLWMatchday")).intValue();
            JSONArray matchesConfig = (JSONArray)((JSONObject) this.matchdayConfig.get(i)).get("matchesConfig");
            ArrayList<APIFootballMatch> apiFootballMatchesForMatchday = getAPIFootballMatchesForMatchday(matchesConfig);

            int tempNumberOfMatchesBackup = this.matchesPerMatchday;
            if(((JSONObject) this.matchdayConfig.get(i)).containsKey("numberOfMatches")) {
                this.matchesPerMatchday = ((Long) ((JSONObject) this.matchdayConfig.get(i)).get("numberOfMatches")).intValue();
            }

            int matchdayMatchCounter = 0;

            // Use first matchtime because API Football always returns matches sorted by date
            LocalDateTime firstDate = TLWMatchesManagerBase.getFirstMatchtimeAPIFootball(apiFootballMatchesForMatchday);

            for(APIFootballMatch match : apiFootballMatchesForMatchday) {
                int matchNo = this.nextMatchNo;
                this.nextMatchNo++;
                int status = 0;
                LocalDateTime matchDateTime = TLWMatchesManagerBase.getDate(match);
                if(firstDate != null && TLWMatchesManagerBase.getDaysDifference(firstDate, matchDateTime) >= 1) {
                    status = -1;
                }
                this.TLWMatches.add(new TLWMatch(match, this.season, this.league, TLWMatchday, matchNo, status, this.ko));
                matchdayMatchCounter++;
                if(firstDate == null) {
                    firstDate = matchDateTime;
                }
            }

            // Add empty missing matches
            for(int j = matchdayMatchCounter; j < this.matchesPerMatchday; j++) {
                String matchDatetime = "";
                if(((JSONObject) matchesConfig.get(0)).get("type").toString().equals("ToBeDefined")) {
                    matchDatetime = ((JSONObject) matchesConfig.get(0)).get("placeholderDatetime").toString();
                }
                else if(apiFootballMatchesForMatchday.size() > 0) {
                    matchDatetime = this.TLWMatches.get(this.TLWMatches.size() - 1).getMatchDateTime();
                }
                int matchNo = this.nextMatchNo;
                this.nextMatchNo++;
                this.TLWMatches.add(new TLWMatch(this.season, this.league, TLWMatchday, matchNo, matchDatetime, 0, this.ko));
            }

            if(((JSONObject) this.matchdayConfig.get(i)).containsKey("numberOfMatches")) {
                this.matchesPerMatchday = tempNumberOfMatchesBackup;
            }
        }
    }

    private ArrayList<APIFootballMatch> getAPIFootballMatchesForMatchday(JSONArray config) {
        ArrayList<APIFootballMatch> apiFootballMatches = new ArrayList<>();
        for (Object singleConfigObject : config) {
            JSONObject singleConfig = (JSONObject) singleConfigObject;
            String type = (String) singleConfig.get("type");
            switch (type) {
                case "AllMatchesOfMatchday":
                    int matchesLeague = ((Long) singleConfig.get("matchesLeague")).intValue();
                    int leagueMatchday = ((Long) singleConfig.get("leagueMatchday")).intValue();
                    apiFootballMatches.addAll(conn.getMatchDataByLeagueAndMatchday(matchesLeague, leagueMatchday));
                    break;
                case "SingleMatch":
                    int matchLeague = ((Long) singleConfig.get("matchLeague")).intValue();
                    int matchId = ((Long) singleConfig.get("matchId")).intValue();
                    apiFootballMatches.add(conn.getMatchDataByLeagueAndMatchID(matchLeague, matchId));
                    break;
            }
        }
        return apiFootballMatches;
    }
}
