package com.ygames.ysoccer.screens;

import com.badlogic.gdx.files.FileHandle;
import com.ygames.ysoccer.competitions.Competition;
import com.ygames.ysoccer.competitions.League;
import com.ygames.ysoccer.framework.Assets;
import com.ygames.ysoccer.framework.GLGame;
import com.ygames.ysoccer.framework.GLScreen;
import com.ygames.ysoccer.framework.TeamList;
import com.ygames.ysoccer.gui.Button;
import com.ygames.ysoccer.gui.Label;
import com.ygames.ysoccer.gui.MenuTheme;
import com.ygames.ysoccer.gui.Widget;
import com.ygames.ysoccer.match.Team;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import static com.ygames.ysoccer.framework.Assets.fileComparatorByName;
import static com.ygames.ysoccer.framework.Assets.font10;
import static com.ygames.ysoccer.framework.Assets.font14;
import static com.ygames.ysoccer.framework.Assets.gettext;
import static com.ygames.ysoccer.framework.Font.Align.CENTER;
import static com.ygames.ysoccer.framework.Font.Align.LEFT;
import static com.ygames.ysoccer.match.Team.ControlMode.COMPUTER;
import static com.ygames.ysoccer.match.Team.ControlMode.PLAYER;
import static com.ygames.ysoccer.match.Team.Type.CLUB;

class ManagerSelectTeam extends GLScreen {

    private final String status;

    ManagerSelectTeam(GLGame game) {
        this(game, "");
    }

    private ManagerSelectTeam(GLGame game, String status) {
        super(game);
        this.status = status;

        background = game.stateBackground;

        Widget w;

        w = new TitleBar("MANAGER MODE - CHOOSE CLUB", game.stateColor.body);
        widgets.add(w);

        addBreadcrumb();

        if (status.length() > 0) {
            w = new StatusLabel();
            widgets.add(w);
        }

        if (navigation.folder.list(Assets.teamFilenameFilter).length > 0) {
            addLeagueOrTeamButtons();
        } else {
            addFolderButtons();
        }

        w = new AbortButton();
        widgets.add(w);
        if (getSelectedWidget() == null) {
            setSelectedWidget(w);
        }
    }

    private void addBreadcrumb() {
        ArrayList<Widget> breadcrumb = new ArrayList<>();

        FileHandle fh = navigation.folder;
        boolean isDataRoot;
        do {
            isDataRoot = fh.equals(Assets.teamsRootFolder);
            Widget w = new BreadCrumbButton(fh, isDataRoot);
            breadcrumb.add(w);
            fh = fh.parent();
        } while (!isDataRoot);

        Collections.reverse(breadcrumb);
        int x = (game.gui.WIDTH - 960) / 2;
        for (Widget b : breadcrumb) {
            b.setPosition(x, 72);
            x += b.w + 2;
        }
        widgets.addAll(breadcrumb);
    }

    private void addFolderButtons() {
        ArrayList<Widget> list = new ArrayList<>();

        ArrayList<FileHandle> files = new ArrayList<>(Arrays.asList(navigation.folder.list()));
        Collections.sort(files, fileComparatorByName);
        for (FileHandle file : files) {
            if (file.isDirectory()) {
                Widget w = new FolderButton(file);
                list.add(w);
                widgets.add(w);
            }
        }

        if (list.size() > 0) {
            Widget.arrange(game.gui.WIDTH, 380, 34, 20, list);
            setSelectedWidget(list.get(0));
        }
    }

    private void addLeagueOrTeamButtons() {
        ArrayList<String> playableLeagues = loadPlayableLeagueNames();
        boolean singleLeague = playableLeagues.size() == 1;
        if (singleLeague && navigation.league == null) {
            navigation.league = playableLeagues.get(0);
        }

        ArrayList<Widget> list = new ArrayList<>();
        if (playableLeagues.size() > 1 && navigation.league == null) {
            for (String league : playableLeagues) {
                Widget w = new LeagueButton(league);
                list.add(w);
                widgets.add(w);
            }
            Widget.arrange(game.gui.WIDTH, 380, 34, 20, list);
            setSelectedWidget(list.get(0));
            return;
        }

        FileHandle[] teamFileHandles = navigation.folder.list(Assets.teamFilenameFilter);
        for (FileHandle teamFileHandle : teamFileHandles) {
            Team team = Assets.json.fromJson(Team.class, teamFileHandle.readString("UTF-8"));
            team.path = normalizeTeamPath(Assets.getRelativeTeamPath(teamFileHandle));
            if (team.type == CLUB && isTeamPlayable(team, playableLeagues)) {
                Widget w = new TeamButton(team);
                list.add(w);
                widgets.add(w);
            }
        }

        if (list.size() > 0) {
            Collections.sort(list, Widget.widgetComparatorByText);
            Widget.arrange(game.gui.WIDTH, 380, 30, 20, list);
            setSelectedWidget(list.get(0));
        } else if (status.length() == 0) {
            Widget w = new NoLeagueLabel();
            widgets.add(w);
        }
    }

    private ArrayList<String> loadPlayableLeagueNames() {
        ArrayList<String> names = new ArrayList<>();
        FileHandle leaguesFile = getCompetitionFolder().child("leagues.json");
        if (!leaguesFile.exists()) {
            return names;
        }

        League[] leagues = Assets.json.fromJson(League[].class, leaguesFile.readString("UTF-8"));
        for (League league : leagues) {
            if (league.files != null && league.files.teams != null && league.files.teams.size() > 0) {
                names.add(league.files.league);
            }
        }
        Collections.sort(names);
        return names;
    }

    private boolean isTeamPlayable(Team team, ArrayList<String> playableLeagues) {
        return navigation.league == null
                ? playableLeagues.contains(team.league)
                : navigation.league.equals(team.league);
    }

    private FileHandle getCompetitionFolder() {
        return Assets.competitionsRootFolder.child(normalizeTeamPath(Assets.getRelativeTeamPath(navigation.folder)));
    }

    private void startManagerMode(Team selectedTeam) {
        selectedTeam.path = normalizeTeamPath(selectedTeam.path);
        League league = findLeague(selectedTeam);
        if (league == null) {
            game.setScreen(new ManagerSelectTeam(game, "NO LEAGUE FOUND FOR " + selectedTeam.name));
            return;
        }

        TeamList teamList = Team.loadTeamList(league.files.teams);
        boolean foundManagerTeam = false;
        for (Team team : teamList) {
            team.path = normalizeTeamPath(team.path);
            if (team.path.equals(selectedTeam.path)) {
                team.controlMode = PLAYER;
                foundManagerTeam = true;
            } else {
                team.controlMode = COMPUTER;
            }
        }

        if (!foundManagerTeam) {
            game.setScreen(new ManagerSelectTeam(game, "NO LEAGUE FOUND FOR " + selectedTeam.name));
            return;
        }

        league.category = Competition.Category.PRESET_COMPETITION;
        league.managerMode = true;
        league.managerTeamPath = selectedTeam.path;
        league.start(teamList);

        navigation.competition = league;
        navigation.folder = Assets.teamsRootFolder.child(league.files.folder);
        navigation.league = league.files.league;
        game.setCompetition(league);
        game.setScreen(new PlayLeague(game));
    }

    private League findLeague(Team selectedTeam) {
        FileHandle leaguesFile = getCompetitionFolder().child("leagues.json");
        if (!leaguesFile.exists()) {
            return null;
        }

        String teamPath = normalizeTeamPath(selectedTeam.path);
        League[] leagues = Assets.json.fromJson(League[].class, leaguesFile.readString("UTF-8"));
        for (League league : leagues) {
            if (containsTeam(league, teamPath)
                    && (navigation.league == null
                    || navigation.league.equals(league.files.league)
                    || selectedTeam.league.equals(league.files.league))) {
                return league;
            }
        }

        for (League league : leagues) {
            if (containsTeam(league, teamPath)) {
                return league;
            }
        }
        return null;
    }

    private boolean containsTeam(League league, String teamPath) {
        if (league.files == null || league.files.teams == null) {
            return false;
        }
        for (String path : league.files.teams) {
            if (normalizeTeamPath(path).equals(teamPath)) {
                return true;
            }
        }
        return false;
    }

    private String normalizeTeamPath(String path) {
        if (path == null) {
            return "";
        }
        int dataTeams = path.indexOf("data/teams/");
        if (dataTeams != -1) {
            path = path.substring(dataTeams + "data/teams/".length());
        }
        while (path.startsWith("/")) {
            path = path.substring(1);
        }
        return path;
    }

    private class StatusLabel extends Label {

        StatusLabel() {
            setGeometry((game.gui.WIDTH - 600) / 2, 110, 600, 28);
            setText(status, CENTER, font10);
        }
    }

    private class NoLeagueLabel extends Label {

        NoLeagueLabel() {
            setGeometry((game.gui.WIDTH - 600) / 2, 300, 600, 32);
            setText("NO MANAGER LEAGUE FOUND HERE", CENTER, font14);
        }
    }

    private class BreadCrumbButton extends Button {

        private final FileHandle folder;

        BreadCrumbButton(FileHandle folder, boolean isDataRoot) {
            this.folder = folder;
            setSize(0, 32);
            if (folder.equals(navigation.folder)) {
                setColors(game.stateColor.darker());
                setActive(false);
            } else {
                setColors(game.stateColor);
            }
            setText(isDataRoot ? "" + (char) 20 : folder.name().replace('_', ' '), CENTER, font10);
            autoWidth();
        }

        @Override
        public void onFire1Down() {
            navigation.folder = folder;
            navigation.league = null;
            game.setScreen(new ManagerSelectTeam(game));
        }
    }

    private class FolderButton extends Button {

        private final FileHandle folder;

        FolderButton(FileHandle folder) {
            this.folder = folder;
            setSize(340, 32);
            setColors(MenuTheme.ACTION);
            setText(folder.name().replace('_', ' '), CENTER, font14);
        }

        @Override
        public void onFire1Down() {
            navigation.folder = folder;
            navigation.league = null;
            game.setScreen(new ManagerSelectTeam(game));
        }
    }

    private class LeagueButton extends Button {

        LeagueButton(String league) {
            setSize(340, 32);
            setColors(MenuTheme.VALUE);
            setText(league, CENTER, font14);
        }

        @Override
        public void onFire1Down() {
            navigation.league = text;
            game.setScreen(new ManagerSelectTeam(game));
        }
    }

    private class TeamButton extends Button {

        private final Team team;

        TeamButton(Team team) {
            this.team = team;
            setSize(270, 28);
            setColors(MenuTheme.ACTION);
            setText(team.name, CENTER, font14);
        }

        @Override
        public void onFire1Down() {
            startManagerMode(team);
        }
    }

    private class AbortButton extends Button {

        AbortButton() {
            setColors(MenuTheme.DANGER);
            setText(gettext("ABORT"), CENTER, font14);
            setGeometry((game.gui.WIDTH - 180) / 2, 660, 180, 36);
        }

        @Override
        public void onFire1Down() {
            game.setScreen(new Main(game));
        }
    }
}
