package io.github.lonamiwebs.klooni.screens;


import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.InputListener;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.HorizontalGroup;
import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane;
import com.badlogic.gdx.scenes.scene2d.ui.Table;
import com.badlogic.gdx.scenes.scene2d.ui.VerticalGroup;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;

import io.github.lonamiwebs.klooni.Klooni;
import io.github.lonamiwebs.klooni.Theme;
import io.github.lonamiwebs.klooni.actors.MoneyBuyBand;
import io.github.lonamiwebs.klooni.actors.SoftButton;
import io.github.lonamiwebs.klooni.actors.ThemeCard;
import io.github.lonamiwebs.klooni.game.GameLayout;

// Screen where the user can customize the look and feel of the game
class CustomizeScreen implements Screen {

    //region Members

    private Klooni game;
    private Stage stage;

    private final Screen lastScreen;

    private float themeDragStartX, themeDragStartY;

    //endregion

    //region Static members

    // As the examples show on the LibGdx wiki
    private static final float MIN_DELTA = 1/30f;
    private static final float DRAG_LIMIT_SQ = 20*20;

    //endregion

    //region Constructor

    CustomizeScreen(Klooni game, final Screen lastScreen) {
        final GameLayout layout = new GameLayout();

        this.game = game;
        this.lastScreen = lastScreen;
        stage = new Stage();

        Table table = new Table();
        table.setFillParent(true);
        stage.addActor(table);

        HorizontalGroup optionsGroup = new HorizontalGroup();
        optionsGroup.space(12);

        // Back to the previous screen
        final SoftButton backButton = new SoftButton(1, "back_texture");
        backButton.addListener(new ChangeListener() {
            @Override
            public void changed(ChangeEvent event, Actor actor) {
                goBack();
            }
        });
        optionsGroup.addActor(backButton);

        // Turn sound on/off
        final SoftButton soundButton = new SoftButton(
                0, Klooni.soundsEnabled() ? "sound_on_texture" : "sound_off_texture");

        soundButton.addListener(new ChangeListener() {
            @Override
            public void changed(ChangeEvent event, Actor actor) {
                final boolean enabled = Klooni.toggleSound();
                soundButton.image = CustomizeScreen.this.game.skin.getDrawable(
                        enabled ? "sound_on_texture" : "sound_off_texture");
            }
        });
        optionsGroup.addActor(soundButton);

        // Snap to grid on/off
        final SoftButton snapButton = new SoftButton(
                2, Klooni.shouldSnapToGrid() ? "snap_on_texture" : "snap_off_texture");

        snapButton.addListener(new ChangeListener() {
            @Override
            public void changed(ChangeEvent event, Actor actor) {
                final boolean shouldSnap = Klooni.toggleSnapToGrid();
                snapButton.image = CustomizeScreen.this.game.skin.getDrawable(
                        shouldSnap ? "snap_on_texture" : "snap_off_texture");
            }
        });
        optionsGroup.addActor(snapButton);

        // Issues
        final SoftButton issuesButton = new SoftButton(3, "issues_texture");
        issuesButton.addListener(new ChangeListener() {
            @Override
            public void changed(ChangeEvent event, Actor actor) {
                Gdx.net.openURI("https://github.com/LonamiWebs/Klooni1010/issues");
            }
        });
        optionsGroup.addActor(issuesButton);

        // Website
        final SoftButton webButton = new SoftButton(2, "web_texture");
        webButton.addListener(new ChangeListener() {
            @Override
            public void changed(ChangeEvent event, Actor actor) {
                Gdx.net.openURI("https://lonamiwebs.github.io");
            }
        });
        optionsGroup.addActor(webButton);

        // Use the same height as the buttons (for instance, the back button)
        table.add(new ScrollPane(optionsGroup))
                .pad(20, 4, 12, 4).height(backButton.getHeight());

        // Load all the available themes
        final MoneyBuyBand buyBand = new MoneyBuyBand(game);

        table.row();
        final VerticalGroup themesGroup = new VerticalGroup();
        for (Theme theme : Theme.getThemes()) {
            final ThemeCard card = new ThemeCard(game, layout, theme);
            card.addListener(new InputListener() {
                @Override
                public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
                    themeDragStartX = x;
                    themeDragStartY = y;
                    return true;
                }

                // We could actually rely on touchDragged not being called,
                // but perhaps it would be hard for some people not to move
                // their fingers even the slightest bit, so we use a custom
                // drag limit

                @Override
                public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
                    x -= themeDragStartX;
                    y -= themeDragStartY;
                    float distSq = x * x + y * y;
                    if (distSq < DRAG_LIMIT_SQ) {
                        if (Klooni.isThemeBought(card.theme))
                            card.use();
                        else
                            buyBand.askBuy(card);

                        for (Actor a : themesGroup.getChildren()) {
                            ThemeCard c = (ThemeCard)a;
                            c.usedThemeUpdated();
                        }
                    }
                }
            });
            themesGroup.addActor(card);
        }

        final ScrollPane themesScroll = new ScrollPane(themesGroup);
        table.add(themesScroll).expand().fill();

        // Show the current money row
        table.row();
        table.add(buyBand).expandX().fillX();

        // Scroll to the currently selected theme
        table.layout();
        for (Actor a : themesGroup.getChildren()) {
            ThemeCard c = (ThemeCard)a;
            if (c.isUsed()) {
                themesScroll.scrollTo(
                        c.getX(), c.getY() + c.getHeight(),
                        c.getWidth(), c.getHeight());
                break;
            }
            c.usedThemeUpdated();
        }
    }

    //endregion

    //region Private methods

    private void goBack() {
        CustomizeScreen.this.game.transitionTo(lastScreen);
    }

    //endregion

    //region Public methods

    @Override
    public void show() {
        Gdx.input.setInputProcessor(stage);
    }

    @Override
    public void render(float delta) {
        Klooni.theme.glClearBackground();
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
        stage.act(Math.min(Gdx.graphics.getDeltaTime(), MIN_DELTA));
        stage.draw();

        if (Gdx.input.isKeyJustPressed(Input.Keys.BACK)) {
            goBack();
        }
    }

    @Override
    public void resize(int width, int height) {
        stage.getViewport().update(width, height, true);
    }

    @Override
    public void dispose() {
        stage.dispose();
    }

    //endregion

    //region Empty methods

    @Override
    public void pause() { }

    @Override
    public void resume() { }

    @Override
    public void hide() { }

    //endregion
}
