package com.codingame.game.engine;


import com.codingame.game.Player;
import com.codingame.gameengine.core.SoloGameManager;
import com.codingame.gameengine.module.entities.GraphicEntityModule;

import java.util.ArrayDeque;
import java.util.HashSet;
import java.util.Properties;
import java.util.Queue;


public class Engine
{
  private SoloGameManager<Player> manager;
  private GraphicEntityModule graphic;

  public GameState state;
  public int solutionLength;
  public String playerInput;



  public Engine(SoloGameManager<Player> manager)
  {
    this.manager = manager;

    // Depth movingPlayer whiteKing whiteRook blackKing
    String[] setup = manager.getTestCaseInput().get(0).split(" ");
    solutionLength = Integer.parseInt(setup[0]);
    playerInput = manager.getTestCaseInput().get(0).split(" ",2)[1];


    state = new GameState(setup);

    System.out.println(setup[2] + " wK -> " + Constants.CoordinatesStrToNum(setup[2]) + " -> " + Constants.CoordinatesNumToStr(Constants.CoordinatesStrToNum(setup[2])));
    System.out.println(setup[3] + " wR -> " + Constants.CoordinatesStrToNum(setup[3]) + " -> " + Constants.CoordinatesNumToStr(Constants.CoordinatesStrToNum(setup[3])));
    System.out.println(setup[4] + " bK -> " + Constants.CoordinatesStrToNum(setup[4]) + " -> " + Constants.CoordinatesNumToStr(Constants.CoordinatesStrToNum(setup[4])));


  }

  // (100 whiteRook ; 200 whiteKing; 300 blackKing) + to square
  public int validateAction(String move) throws InvalidActionException
  {
    int from = Constants.CoordinatesStrToNum(move.substring(0,2));
    int to = Constants.CoordinatesStrToNum(move.substring(2,4));

    if (state.whiteToMove && from==state.whiteRook && state.whiteRookAction.contains(to)) return 100 + to;
    if (state.whiteToMove && from==state.whiteKing && state.whiteKingAction.contains(to)) return 200 + to;
    if (!state.whiteToMove && from==state.blackKing && state.blackKingAction.contains(to)) return 300 + to;

    throw new InvalidActionException(String.format("Given move '%s' is illegal in the current game state.", move));
  }

  public static GameState BFS(GameState root)
  {
    Queue<GameState> queue = new ArrayDeque<>();
    HashSet<GameState> visited = new HashSet<>();
    GameState s;

    queue.add(root);

    while (!queue.isEmpty())
    {
      GameState state = queue.remove();

      if (state.mate)
        return state;

      if (state.whiteToMove)
      {
        for (int to : state.whiteRookAction)
        {
          s = new GameState(state, 100+to);
          if (visited.contains(s)) continue;
          visited.add(s);
          queue.add(s);
        }
        for (int to : state.whiteKingAction)
        {
          s = new GameState(state, 200+to);
          if (visited.contains(s)) continue;
          visited.add(s);
          queue.add(s);
        }
      }
      else
      {
        for (int to : state.blackKingAction)
        {
          s = new GameState(state, 300+to);
          if (visited.contains(s)) continue;
          visited.add(s);
          queue.add(s);
        }
      }
    }
    return null;
  }


}
