package com.codingame.game;

import com.codingame.game.engine.*;
import com.codingame.game.modules.MyViewportModule;
import com.codingame.gameengine.core.AbstractPlayer.TimeoutException;
import com.codingame.gameengine.core.AbstractReferee;
import com.codingame.gameengine.core.SoloGameManager;
import com.codingame.gameengine.module.tooltip.TooltipModule;
import com.codingame.gameengine.module.entities.*;
import com.google.inject.Inject;


import java.util.Locale;

import static com.codingame.game.engine.Constants.*;

public class Referee extends AbstractReferee
{
  @Inject private SoloGameManager<Player> manager;
  @Inject private GraphicEntityModule graphic;
  @Inject private TooltipModule tooltip;
  @Inject private MyViewportModule viewportModule;

  private Engine engine;
  private Viewer viewer;
  private Player player;

  @Override
  public void init()
  {
    Locale.setDefault(new Locale("en", "US"));

    engine = new Engine(manager); //engine.TEST();

    player = manager.getPlayer();
    player.expectedOutputLines = 1;

    manager.setFirstTurnMaxTime(Constants.TIMELIMIT_INIT);
    manager.setTurnMaxTime(Constants.TIMELIMIT_TURN);
    manager.setMaxTurns(Constants.TURNLIMIT);
    manager.setFrameDuration(Constants.FRAMEDURATION);

    viewer = new Viewer(graphic, manager, tooltip, engine);
    viewer.init();

    //viewportModule.createViewport(viewer.envGroup);
    //viewportModule.createViewport(viewer.blackGroup);

    engine.step(0);
    viewer.step(0);
    viewportModule.createViewport(viewer.viewportGroup);

    graphic.commitWorldState(0);
    //viewportModule.createViewport(viewer.envGroup);

  }

  @Override
  public void gameTurn(int turn)
  {
    if (engine.lazzieXY == engine.homeXY || turn > engine.turnlimit)
    {
      manager.setFrameDuration(Constants.FRAMEDURATION_SUMMARY);
      boolean passed = engine.lazzieXY == engine.homeXY && turn <= engine.turnlimit;
      viewer.showSummary(passed);
      if (passed) manager.winGame("Congratulations!\nLazzie safely came home.");
      else        manager.loseGame("You took too long.\nLazzie cannot go hungry forever!");
      return;
    }

    //manager.addTooltip(manager.getPlayer(), "Map");
    if (turn == 1) manager.getPlayer().sendInputLine(String.format("%d %d %d", engine.radius*2+1, X(engine.homeXY)-X(engine.lazzieXY), Y(engine.homeXY)-Y(engine.lazzieXY)));
    manager.getPlayer().sendInputLine(engine.toString());
    if (!executePlayer()) {
      // todo viewer step false
      // show summary failed?
      return;
    }

    engine.step(turn);
    viewer.step(turn);




    //viewportModule.createViewport(viewer.envGroup);
    graphic.commitWorldState(1);
  }

  @Override
  public void onEnd()
  {
    //manager.putMetadata("Score", ""+gameState.score);
  }

  private boolean executePlayer()
  {
    try
    {
      manager.getPlayer().execute();;
      engine.validateAnswer(manager.getPlayer().getOutputs());
      return true;
    }
    catch (ActionErrorException e)
    {
      manager.setFrameDuration(Constants.FRAMEDURATION_SUMMARY);
      viewer.showSummary(false);
      manager.loseGame(e.getMessage());
      return false;
    }
    catch (TimeoutException e)
    {
      manager.setFrameDuration(Constants.FRAMEDURATION_SUMMARY);
      viewer.showSummary(false);
      manager.loseGame("[ERROR] Timeout!");
      return false;
    }
    catch (Exception e)
    {
      manager.setFrameDuration(Constants.FRAMEDURATION_SUMMARY);
      viewer.showSummary(false);
      manager.loseGame(String.format("[ERROR] Output not properly formatted. Should be 'landmarksNum' lines with landmark 'column row' position each .", player.getExpectedOutputLines()));
      return false;
    }
  }
}
