package cicaprojekt;

import javax.swing.*;
import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.util.Map;

public class Game {
    private Player oneill;
    private Player jaffa;

    private PlayerBase replicator;

    private Dungeon dungeon;
    private FlowOfTime flowoftime;

    private Display display;

    public static Game instance = new Game();
    
    private Game() {}

    public void playerBaseDestroyed(PlayerBase caller) {
        Field field = new Field();
        Tile callertile = caller.getCurrentTile();

        field.setX(callertile.getX());
        field.setY(callertile.getY());

        field.setAdajacentTile(caller.getCurrentTile().getAdjacentTile(Direction.NORTH), Direction.NORTH);
        callertile.getAdjacentTile(Direction.NORTH).setAdajacentTile(field, Direction.SOUTH);

        field.setAdajacentTile(caller.getCurrentTile().getAdjacentTile(Direction.SOUTH), Direction.SOUTH);
        callertile.getAdjacentTile(Direction.SOUTH).setAdajacentTile(field, Direction.NORTH);

        field.setAdajacentTile(caller.getCurrentTile().getAdjacentTile(Direction.WEST), Direction.WEST);
        callertile.getAdjacentTile(Direction.WEST).setAdajacentTile(field, Direction.EAST);

        field.setAdajacentTile(caller.getCurrentTile().getAdjacentTile(Direction.EAST), Direction.EAST);
        callertile.getAdjacentTile(Direction.EAST).setAdajacentTile(field, Direction.WEST);

        display.gapMagic((Gap)callertile, field, dungeon.getMapWidth());

        Game.instance.updateDisplay();
    }

    public void playerDestroyed(Player caller) {
        dungeon.setZPMsToWin(dungeon.getZPMsToWin() - caller.getZPMCount());
        Game.instance.updateDisplay();
    }

    public void setDungeon(Dungeon dungeon) {
        this.dungeon = dungeon;
    }

    public void setDisplay(Display display) {
        this.display = display;
    }

    public void allZPMsCollected(GameoverCause cause) {
        this.stopGame(cause);
    }

    public void startGame(File dungeonFile) throws IOException {
        Stargate.init();

        Map<String, Tile> players = dungeon.buildDungeon(dungeonFile, display);
        oneill = new Player("O'Neill", players.get("oneill"), Direction.getRandom());
        jaffa = new Player("Jaffa", players.get("jaffa"), Direction.getRandom());
        replicator = new PlayerBase("Replicator", players.get("replicator"), Direction.getRandom());
        
        display.addVisual(new PlayerDrawer(oneill));
        display.addVisual(new PlayerDrawer(jaffa));
        display.addVisual(new PlayerBaseDrawer(replicator));

        flowoftime = new FlowOfTime();
        flowoftime.start(dungeon.getTimeLimit());
    }

    public void stopGame(GameoverCause cause) {
        switch (cause){

            case TIMEOUT:
                JOptionPane.showMessageDialog(null, "Time is up! Anubis has enslaved the world by now.",
                                              "Game over",
                                              JOptionPane.INFORMATION_MESSAGE,
                                              new ImageIcon("Anubis.png"));
                Application.frameInstance.backToMapSelection();
                break;
            case ONEILLWON:
                JOptionPane.showMessageDialog(null, "Colonel O'Neill won!", "Game over",
                                              JOptionPane.INFORMATION_MESSAGE,
                                              new ImageIcon("Deal_with_iit.png"));
                Application.frameInstance.backToMapSelection();
                break;
            case JAFFAWON:
                JOptionPane.showMessageDialog(null, "Jaffa won!", "Game over",
                                              JOptionPane.INFORMATION_MESSAGE,
                                              new ImageIcon("Deal_with_iit.png"));
                Application.frameInstance.backToMapSelection();
                break;
        }
    }

    public void moveONeill(Direction direction) {
        oneill.move(direction);
        checkZPMStatus();
    }

    public void moveJaffa(Direction direction) {
        jaffa.move(direction);
        checkZPMStatus();
    }

    public void moveReplicator(Direction direction) {
        replicator.move(direction);
    }

    public void rotateOneillLeft() {
        oneill.rotateLeft();
    }

    public void rotateOneillRight() {
        oneill.rotateRight();
    }

    public void rotateJaffaLeft() {
        jaffa.rotateLeft();
    }

    public void rotateJaffaRight() {
        jaffa.rotateRight();
    }

    public void boxONeill() {
        if(oneill.hasBox())
            oneill.boxDrop();
        else
            oneill.boxLift();
    }

    public void boxJaffa() {
        if(jaffa.hasBox())
            jaffa.boxDrop();
        else
            jaffa.boxLift();
    }

    public void shootStargate(Color color) {
        if(color == Color.YELLOW || color == Color.BLUE)
            oneill.shootStargate(Stargate.get(color));
        else
            jaffa.shootStargate(Stargate.get(color));
    }

    public void updateDisplay() {
        try {
            display.drawVisuals();
            display.repaint();
        }
        catch (IOException e) {
            Control.ioErrorMessage();
        }
    }

    private void checkZPMStatus()
    {
        if (oneill.getZPMCount() >= dungeon.getZPMsToWin())
        {
            flowoftime.stopTime();
            stopGame(GameoverCause.ONEILLWON);
        }
        else if (jaffa.getZPMCount() >= dungeon.getZPMsToWin())
        {
            flowoftime.stopTime();
            stopGame(GameoverCause.JAFFAWON);
        }
    }
}
