package com.codingame.view;


import com.codingame.game.Card;
import com.codingame.game.Game;
import com.codingame.game.Player;
import com.codingame.gameengine.core.MultiplayerGameManager;
import com.codingame.gameengine.module.entities.BitmapText;
import com.codingame.gameengine.module.entities.GraphicEntityModule;
import com.codingame.gameengine.module.entities.Group;
import com.codingame.gameengine.module.entities.Sprite;
import com.codingame.view.tooltip.TooltipModule;
import com.codingame.view.tooltip.TooltipGlobalData;
import com.google.inject.Inject;
import com.google.inject.Singleton;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static java.lang.Math.min;

@Singleton
public class View {
    @Inject private MultiplayerGameManager<Player> gameManager;
    @Inject private GraphicEntityModule gem;
    @Inject private TooltipModule tooltipModule;

    Sprite background;
    Sprite[] cards;
    BitmapText[] scores;
    BitmapText[] names;
    Sprite[] avatars;
    private int screenWidth;
    private int screenHeight;
    private static final int Z_LAYER_CARD = 5;
    private static final int Z_LAYER_MOVING_CARD = 10;

    int cellSize = 1;
    Group gameZone;

    public void init() {
        background = gem.createSprite().setImage("background.jpg");

        screenWidth = gem.getWorld().getWidth();
        screenHeight = gem.getWorld().getHeight();

        int gameZoneWidth = 2220;
        int gameZoneHeight = 1080;
        gameZone = gem.createGroup();
        double coefficient = fitAspectRatioContains(gameZoneWidth, gameZoneHeight, screenWidth, screenHeight);
        gameZone.setScale(coefficient);
        TooltipGlobalData tooltipData = new TooltipGlobalData(
                gameZoneWidth, gameZoneHeight, gameZone.getX(), gameZone.getY(), cellSize, coefficient
        );
        tooltipModule.init(tooltipData);

        cards = new Sprite[Game.CARD_COUNT];
        for (int i=1;i<=Game.CARD_COUNT;i++) {
            Sprite card = gem
                    .createSprite()
                    .setImage(i+".png")
                    .setVisible(true);
            cards[i-1] = card;
        }

        scores = new BitmapText[gameManager.getPlayerCount()];
        names = new BitmapText[gameManager.getPlayerCount()];
        avatars = new Sprite[gameManager.getPlayerCount()];
        int avatarSize = 110;
        Integer[] playerScoreX = new Integer[4];
        playerScoreX[0]=100;
        playerScoreX[1]=1800;
        playerScoreX[2]=100;
        playerScoreX[3]=1800;
        Integer[] playerScoreY = new Integer[4];
        playerScoreY[0]=250;
        playerScoreY[1]=250;
        playerScoreY[2]=750;
        playerScoreY[3]=750;
        for (int i=0;i<gameManager.getPlayerCount();++i) {
            Player player = gameManager.getPlayer(i);

            Sprite avatar = gem.createSprite()
                    .setImage(player.getAvatarToken())
                    .setAnchor(0.5)
                    .setX(playerScoreX[i])
                    .setY(playerScoreY[i])
                    .setBaseHeight(avatarSize)
                    .setBaseWidth(avatarSize)
                    .setZIndex(999);
            avatars[i] = avatar;

            BitmapText nameLabel = gem.createBitmapText()
                    .setFont("BRLNS_66")
                    .setFontSize(30)
                    .setText(player.getNicknameToken())
                    .setAnchorX(0.5)
                    .setX(playerScoreX[i])
                    .setY(playerScoreY[i] + 55)
                    .setZIndex(2);
            names[i] = nameLabel;

            BitmapText scoreLabel = gem.createBitmapText()
                    .setFont("BRLNS_66")
                    .setFontSize(20)
                    .setText("Score: 0")
                    .setAnchorX(0.5)
                    .setX(playerScoreX[i])
                    .setY(playerScoreY[i] + 85)
                    .setZIndex(2);
            scores[i] = scoreLabel;
        }
    }


    private static double fitAspectRatioContains(int srcWidth, int srcHeight, int maxWidth, int maxHeight) {
        return min((double) maxWidth / srcWidth, (double) maxHeight / srcHeight);
    }

    public void initTooltips(Game game) {
        for(Card card : game.getCards()) {
            tooltipModule.setTooltipText(cards[card.getValue()-1], card.getTooltipText());
        }
    }

    public void hideCards(double time) {
        for (int i=0;i<Game.CARD_COUNT;i++) {
            cards[i].setVisible(false);
            gem.commitEntityState(time, cards[i]);
        }
    }

    public void displayCards(Game game, double time, List<Card> cardsToPlay) {
        for (int i=0;i<Game.CARD_COUNT;i++) {
            cards[i].setVisible(false);
        }
        Integer[] playerBaseX = new Integer[4];
        playerBaseX[0]=50;
        playerBaseX[1]=1700;
        playerBaseX[2]=50;
        playerBaseX[3]=1700;
        Integer[] playerBaseY = new Integer[4];
        playerBaseY[0]=50;
        playerBaseY[1]=50;
        playerBaseY[2]=900;
        playerBaseY[3]=900;
        for (Player player : gameManager.getActivePlayers()) {
            int playerId = player.getIndex();
            int x=playerBaseX[playerId];
            int y=playerBaseY[playerId];
            int i=0;
            int cardWidth=80;
            if (playerId%2==1) cardWidth*=-1;
            List<Integer> cardsToDisplay = new ArrayList<>();
            for(Card card : gameManager.getPlayer(playerId).getCards()) {
                cardsToDisplay.add(card.getValue() - 1);
            }
            Collections.sort(cardsToDisplay);
            for(int cardId : cardsToDisplay) {
                cards[cardId]
                        .setY(y)
                        .setX(x + i * cardWidth)
                        .setVisible(true)
                        .setZIndex(Z_LAYER_CARD);
                i++;
                gem.commitEntityState(time, cards[cardId]);
            }
        }

        int lineId=0;
        int lineStartX = 500;
        int lineStartY = 200;
        int cardWidth = 150;
        int lineHeight = 150;
        for(List<Card> line: game.getLines()) {
            int i=0;
            for (Card card : line) {
                cards[card.getValue()-1]
                        .setY(lineStartY + lineId * lineHeight)
                        .setX(lineStartX + i * cardWidth)
                        .setVisible(true)
                        .setZIndex(Z_LAYER_CARD);
                i++;
                gem.commitEntityState(time, cards[card.getValue()-1]);
            }
            lineId++;
        }

        //selected cards are displayed a bit higher
        for(Card card : cardsToPlay) {
            cards[card.getValue()-1].setY(cards[card.getValue()-1].getY() - 40);
            gem.commitEntityState(time, cards[card.getValue()-1]);
        }
    }

    public void updateScore(Player player) {
        scores[player.getIndex()].setText(String.format("Score: %d", player.getScore()));
    }

    public void playCard(int cardId, double time) {
        cards[cardId-1].setZIndex(Z_LAYER_MOVING_CARD);
    }

    public void playerGetsAllCards(List<Card> line, Player player) {
        for(Card card : line) {
            cards[card.getValue()-1].setX(avatars[player.getIndex()].getX()).setY(avatars[player.getIndex()].getY());
            gem.commitEntityState(0.95, cards[card.getValue()-1]);
        }
    }

    public void changeBackground(int round) {
        background.setImage(String.format("background_round_%d.jpg", round));
    }
}
