package eu.jonahbauer.wizard.client.libgdx.screens;

import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.ui.*;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import com.badlogic.gdx.utils.Align;
import eu.jonahbauer.wizard.client.libgdx.WizardGame;
import eu.jonahbauer.wizard.client.libgdx.actors.CardActor;
import eu.jonahbauer.wizard.client.libgdx.listeners.KeyboardFocusManager;
import eu.jonahbauer.wizard.client.libgdx.state.Menu;
import eu.jonahbauer.wizard.client.libgdx.util.WizardAssetManager;
import eu.jonahbauer.wizard.common.model.Card;

public class InstructionScreen extends MenuScreen {
    private static final int MAX_PAGE = 3;

    private TextButton buttonBack;
    private VerticalGroup content;
    private ScrollPane scrollPane;
    private TextButton nextPageButton;
    private TextButton previousPageButton;

    private int currentPage = 0;

    private TextureAtlas atlas;

    private final ChangeListener listener = new ChangeListener() {
        @Override
        public void changed(ChangeEvent event, Actor actor) {
            if (actor == buttonBack) {
                game.getClient().execute(Menu.class, Menu::showMenuScreen);
            } else if (actor == nextPageButton) {
                currentPage = MathUtils.clamp(currentPage + 1, 0, MAX_PAGE);
                showPage(currentPage);
            }  else if (actor == previousPageButton) {
                currentPage = MathUtils.clamp(currentPage - 1, 0, MAX_PAGE);
                showPage(currentPage);
            }
        }
    };

    public InstructionScreen(WizardGame game) {
        super(game);
    }

    @Override
    protected void load() {
        super.load();
        assets.loadGame();
        assets.finishLoading();

        atlas = assets.get(WizardAssetManager.ATLAS_GAME);
    }

    @Override
    public void show() {
        super.show();

        content = new VerticalGroup().left().grow().pad(20);

        getTitle().moveBy(0, 80);
        getButtonGroup().moveBy(0, - 80);

        previousPageButton = new TextButton(messages.get("menu.instruction.previousPageButton"), skin);
        previousPageButton.addListener(listener);
        getButtonGroup().addActor(previousPageButton);

        buttonBack = new TextButton(messages.get("menu.instruction.back"), skin);
        buttonBack.addListener(listener);
        getButtonGroup().addActor(buttonBack);

        nextPageButton = new TextButton(messages.get("menu.instruction.nextPageButton"), skin);
        nextPageButton.addListener(listener);
        getButtonGroup().addActor(nextPageButton);

        scrollPane = new ScrollPane(content, skin);
        scrollPane.setPosition(0.175f * WizardGame.WIDTH, 0.2f * WizardGame.HEIGHT);
        scrollPane.setSize(0.65f * WizardGame.WIDTH, 400 + 0.1f * WizardGame.HEIGHT + 80);
        stage.addActor(scrollPane);

        stage.addCaptureListener(new KeyboardFocusManager(scrollPane, previousPageButton, buttonBack, nextPageButton));

        showFirstPage();
    }

    private void showPage(int page) {
        switch (page) {
            case 0 -> showFirstPage();
            case 1 -> showSecondPage();
            case 2 -> showThirdPage();
            case 3 -> showFourthPage();
            default -> throw new AssertionError();
        }
    }

    private void showFirstPage() {
        currentPage = 0;
        reset();

        startSection("menu.instruction.main.title");
        startSubsection("menu.instruction.main.welcome.title");
        addParagraph("menu.instruction.main.welcome.par0");
        startSubsection("menu.instruction.main.general.title");
        addParagraph("menu.instruction.main.general.par0");
    }

    private void showSecondPage() {
        currentPage = 1;
        reset();

        startSection("menu.instruction.standard.title");
        addParagraph("menu.instruction.standard.par0");

        var colors = new HorizontalGroup().space(10).pad(10).center();
        for (Card.Suit suit : Card.Suit.values()) {
            if (suit != Card.Suit.NONE) {
                VerticalGroup suitGroup = new VerticalGroup().space(10);
                suitGroup.addActor(new CardActor(suit, atlas));
                suitGroup.addActor(new Label(switch (suit) {
                    case RED -> messages.get("menu.instruction.suit.red");
                    case GREEN -> messages.get("menu.instruction.suit.green");
                    case BLUE -> messages.get("menu.instruction.suit.blue");
                    case YELLOW -> messages.get("menu.instruction.suit.yellow");
                    default -> suit.toString();
                }, skin));
                colors.addActor(suitGroup);
            }
        }
        content.addActor(colors);

        addParagraph("menu.instruction.standard.par1");

        var specialCards = new HorizontalGroup().space(10).pad(10).center();

        var wizard = new VerticalGroup();
        wizard.addActor(new CardActor(Card.BLUE_WIZARD, atlas));
        wizard.addActor(new Label(messages.get("menu.instruction.wizard"), skin));
        specialCards.addActor(wizard);

        var jester = new VerticalGroup();
        jester.addActor(new CardActor(Card.BLUE_JESTER, atlas));
        jester.addActor(new Label(messages.get("menu.instruction.jester"), skin));
        specialCards.addActor(jester);

        content.addActor(specialCards);

        addParagraph("menu.instruction.standard.par2");

        startSubsection("menu.instruction.standard.trick.title");
        addParagraph("menu.instruction.standard.trick.par0");

        startSubsection("menu.instruction.standard.special_cases.title");
        addParagraph("menu.instruction.standard.special_cases.par0");

        startSubsection("menu.instruction.standard.scoring.title");
        addParagraph("menu.instruction.standard.scoring.par0");
    }

    private void showThirdPage() {
        currentPage = 2;
        reset();

        startSection("menu.instruction.variant.title");
        addParagraph("menu.instruction.variant.intro");

        Table table = new Table(skin).padTop(10);
        table.defaults().space(10.0f).left().top();
        table.columnDefaults(1).grow();
        table.add(messages.get("menu.instruction.variant.default"));
        table.add(messages.get("menu.instruction.variant.default.description")).getActor().setWrap(true);
        table.row();
        table.add(messages.get("menu.instruction.variant.defaultpm1"));
        table.add(messages.get("menu.instruction.variant.defaultpm1.description")).getActor().setWrap(true);
        table.row();
        table.add(messages.get("menu.instruction.variant.anniversary2016"));
        table.add(messages.get("menu.instruction.variant.anniversary2016.description")).getActor().setWrap(true);
        table.row();
        table.add(messages.get("menu.instruction.variant.anniversary2016pm1"));
        table.add(messages.get("menu.instruction.variant.anniversary2016pm1.description")).getActor().setWrap(true);
        table.row();
        table.add(messages.get("menu.instruction.variant.anniversary2021"));
        table.add(messages.get("menu.instruction.variant.anniversary2021.description")).getActor().setWrap(true);
        table.row();
        table.add(messages.get("menu.instruction.variant.anniversary2021pm1"));
        table.add(messages.get("menu.instruction.variant.anniversary2021pm1.description")).getActor().setWrap(true);
        table.row();
        content.addActor(table);
    }

    private void showFourthPage() {
        currentPage = 3;
        reset();

        startSection("menu.instruction.special_card.title");
        addParagraph("menu.instruction.special_card.intro");

        Table table = new Table(skin).padTop(10);
        table.defaults().space(10.0f).left().top();
        table.columnDefaults(1).grow();
        table.add(new CardActor((Card.DRAGON), atlas));
        table.add(messages.get("menu.instruction.special_card.dragon")).getActor().setWrap(true);
        table.row();
        table.add(new CardActor((Card.FAIRY), atlas));
        table.add(messages.get("menu.instruction.special_card.fairy")).getActor().setWrap(true);
        table.row();
        table.add(new CardActor((Card.BOMB), atlas));
        table.add(messages.get("menu.instruction.special_card.bomb")).getActor().setWrap(true);
        table.row();
        table.add(new CardActor((Card.WEREWOLF), atlas));
        table.add(messages.get("menu.instruction.special_card.werewolf")).getActor().setWrap(true);
        table.row();
        table.add(new CardActor((Card.JUGGLER), atlas));
        table.add(messages.get("menu.instruction.special_card.juggler")).getActor().setWrap(true);
        table.row();
        table.add(new CardActor((Card.CLOUD), atlas));
        table.add(messages.get("menu.instruction.special_card.cloud")).getActor().setWrap(true);
        table.row();
        table.add(new CardActor((Card.CHANGELING), atlas));
        table.add(messages.get("menu.instruction.special_card.changeling")).getActor().setWrap(true);
        table.row();
        content.addActor(table);
    }

    private void reset() {
        updateButtons();
        content.clearChildren();
        scrollPane.setScrollY(0);
        scrollPane.updateVisualScroll();
    }

    private void updateButtons() {
        previousPageButton.setDisabled(currentPage == 0);
        nextPageButton.setDisabled(currentPage == MAX_PAGE);
    }

    private void startSection(String title) {
        if (content.hasChildren()) {
            var spacerPre = new Actor();
            spacerPre.setHeight(20);
            spacerPre.setName("spacer");
            content.addActor(spacerPre);
        }

        var label = new Label(messages.get(title).trim(), skin, "enchanted");
        label.setAlignment(Align.center);
        content.addActor(label);

        var spacerPost = new Actor();
        spacerPost.setHeight(10);
        spacerPost.setName("spacer");
        content.addActor(spacerPost);
    }

    private void startSubsection(String title) {
        if (content.hasChildren() && !"spacer".equals(content.getChild(content.getChildren().size - 1).getName())) {
            var spacerPre = new Actor();
            spacerPre.setHeight(10);
            spacerPre.setName("spacer");
            content.addActor(spacerPre);
        }

        var label = new Label(messages.get(title), skin);
        label.setFontScale(2.0f);
        label.setAlignment(Align.center);
        content.addActor(label);
    }

    private void addParagraph(String paragraph) {
        var label = new Label(messages.get(paragraph), skin);
        label.setAlignment(Align.left);
        label.setWrap(true);
        content.addActor(label);
    }

    @Override
    public void dispose() {
        super.dispose();
        assets.unloadGame();
    }
}
