class GridCell {
  constructor(_id, xpos, ypos) {
    this.id = _id;
    this.x = xpos;
    this.y = ypos;
    this.passed = false;
    this.text = 0;
    this.step = true;
    this.motionDetector = false;
    this.motionID = -2;
  }

  startTimer(interval) {
    var dOld = new Date();
    var nOld;
    if (this.motionID == globalMotionID){
      nOld = globalMotionTime;
    }
    else{
      nOld = dOld.getTime();
    }
    var x = this.x;
    var y = this.y;
    var mid = this.motionID;
    var counter = setInterval(function(){
      var dNow = new Date();
      var nNow = dNow.getTime();
      var ntime =  Math.round(((interval*1000) - (nNow - nOld))/10) / 100;
      if(globalx != x){
        clearInterval(counter);
        globalMotionID = mid;
        globalMotionTime = nOld;
        if (grid[globalx][globaly].motionDetector == true){
          grid[globalx][globaly].startTimer(5);
        }
        else{
          globalMotionID = -1;
          globalMotionTime = 0;
          document.getElementById("timer").innerHTML = 0.00;
          isFirtHardCellClick = true;
        }
      }
      else if (ntime <= 0){
        clearInterval(counter);
        document.getElementById("timer").innerHTML = 0.00;
        state = "endOfGame";
      }
      else{
        document.getElementById("timer").innerHTML = ntime;
      }

      if (document.getElementById("timer").innerHTML == "0"){
        document.getElementById("timer").innerHTML = "0.00";
      }
    }, 1);
  }
}

var width = 0;
var height = 0;
var state;
var cnt = 1;
var grid = [];
var running = false;
var globalx;
var globaly;
var globalMotionID = -1;
var globalMotionTime = 0;
var steps = 0;
var startx = 0;
var starty = 0;
var areas = 0;
var sizes = [];
var isFirtHardCellClick = true;
var hardSizes = [];
var hardCenters = [];

function distance(a, b) {
  const dx = a[0] - b[0];
  const dy = a[1] - b[1];
  return(Math.sqrt(dx*dx + dy*dy));   //Math.hypot(dx, dy)
}

function start() {
  if (!running) {
    running = true;
    generate();
    if (document.getElementById("hard").checked == true)
    {
      document.getElementById("timer").innerHTML = "0.0";
      areas = Math.floor(height*width/20);

      for (let i = 0; i < areas && i < 4; i++)
      {
          sizes.push(3 + i * 2);
      }
      hardMode();
    }
  }
}

function time() {
  var dOld = new Date();
  var nOld = dOld.getTime();
  if (state != "endOfGame") {
    var counter = setInterval(function(){
      var dNow = new Date();
      var nNow = dNow.getTime();
      timeElasped = Math.floor((nNow-nOld) / 1000);
      document.getElementById("counter").innerHTML = timeElasped;
      if(state == "endOfGame"){
        clearInterval(counter);
        if (cnt == width * height + 1) {
          result = circleSolution();
          if (result) {
            alert("GG! Ön egy körútvonalat talált!!! Noice!");
            reset();
          }
          else{
            alert("Nyertél!");
            reset();
          }
        }
        else {
          alert("Vesztettél!");
          reset();
        }
      }
    }, 10);
  }
}

function generate() {
  width = parseInt(document.getElementById("width").value);
  height = parseInt(document.getElementById("height").value);
  id = 0;
  if (width >= 5 && height >= 5) {
    table = document.getElementById("table");
    for (let i = 0; i < height; i++) {
      row = table.insertRow(-1);
      grid.push([]);
      for (let j = 0; j < width; j++) {
          grid[i].push(new GridCell(id, i, j));
          cell = row.insertCell(-1);
          cell.setAttribute("class", "cell");
          cell.setAttribute("id", id);
          cell.setAttribute("onclick", "cellClick(" + id + ", " + i + ", " + j + ")");
          id += 1;
      }
    }
  }
  else {
    state = "endOfGame";
    alert("Rossz adat!");
  }
}

function cellClick(id, i, j) {
  if (grid[i][j].step)
  {
    document.getElementById(grid[i][j].id).classList.toggle("currentCell", true);
    grid[i][j].passed = true;
    grid[i][j].text = cnt;
    if (cnt == 1) {
      time();
      startx = j;
      starty = i;
      for (let k = 0; k < height; k++)
      {
        for (let l = 0; l < width; l++)
        {
          document.getElementById(grid[k][l].id).classList.toggle("cell", false);
        }
      }
    }
    else {
      document.getElementById(grid[globalx][globaly].id).classList.toggle("currentCell", false);
      document.getElementById(grid[globalx][globaly].id).classList.toggle("passedCell", true);
    }
    globalx = i;
    globaly = j;
    cnt += 1;
    document.getElementById(id).innerHTML = grid[i][j].text;
    search();
    if (isFirtHardCellClick && grid[i][j].motionDetector == true){
      if (grid[i][j].motionDetector == true){
         grid[i][j].startTimer(5);
       }
       else{
        globalMotionID = -1;
         globalMotionTime = 0;
         document.getElementById("timer").innerHTML = 0.00;
       }
       isFirtHardCellClick = false;
    }

  }
}

function search() {
  steps = 0;
  for (i = 0; i < height; i++)
  {
    for (j = 0; j < width; j++)
    {
      grid[i][j].step = false;
      document.getElementById(grid[i][j].id).classList.toggle("stepCell", false);
    }
  }
  cellCheck(globalx+2, globaly-1);
  cellCheck(globalx+2, globaly+1);
  cellCheck(globalx-2, globaly-1);
  cellCheck(globalx-2, globaly+1);
  cellCheck(globalx-1, globaly-2);
  cellCheck(globalx-1, globaly+2);
  cellCheck(globalx+1, globaly-2);
  cellCheck(globalx+1, globaly+2);
  if (steps == 0)
  {
    running = false;
    state = "endOfGame";
  }
}

function cellCheck(targetx, targety) {
  if (grid[targetx] != undefined)
  {
    if (grid[targetx][targety] != undefined)
    {
      if (grid[targetx][targety].text == 0)
      {
        grid[targetx][targety].step = true;
        document.getElementById(grid[targetx][targety].id).classList.toggle("stepCell", true);
        steps++;
      }
    }
  }
}

function circleSolution(){
  if (globalx - 1 == startx && globaly - 2 == starty) {
    return true;
  }
  else if (globalx + 1 == startx && globaly - 2 == starty) {
    return true;
  }
  else if (globalx - 2 == startx && globaly - 1 == starty) {
    return true;
  }
  else if (globalx - 2 == startx && globaly + 1 == starty) {
    return true;
  }
  else if (globalx + 2 == startx && globaly - 1 == starty) {
    return true;
  }
  else if (globalx + 1 == startx && globaly + 1 == starty) {
    return true;
  }
  else if (globalx - 1 == startx && globaly + 2 == starty) {
    return true;
  }
  else if (globalx + 1 == startx && globaly + 2 == starty) {
    return true;
  }
  else{
    return false;
  }
}

var hc = 0;
function hardMode() {
  for (let i = 0; i < areas; i++)
  {
    var centers = [];
    hardSizes.push(sizes[Math.floor(Math.random()*sizes.length)]);
    var circle = false;
    for (let j = 0; j < grid.length; j++){
      for (let k = 0; k < grid[j].length; k++){
        var result = isAway([j, k]);
        if (result){
          centers.push([j, k]);
          circle = true;
        }
      }
    }
    if (circle){
      hardCenters.push(centers[Math.floor(Math.random() * centers.length)]);
      createCircle(hardSizes[i], hardCenters[i], i);
    }
    else{
      hardCenters.push([-1000, -1000]);
      hc++;
    }
  }
  console.log(hc);
}

function isAway(o) {
  for (let i = 0; i < hardCenters.length; i++) {
    if (distance(o, hardCenters[i]) < (hardSizes[i] - 1) / 2 + (hardSizes[hardSizes.length -1] - 1) / 2 + 1.5)
    {
      return false;
    }
  }
  return true;
}

function createCircle(size, pos, id) {
  hardCells(pos[0], pos[1]);
  for (var i = 0; i < (size - 1) / 2; i++) {
    hardCells(pos[0] + i + 1, pos[1], id);
    hardCells(pos[0] - (i + 1), pos[1], id);
    hardCells(pos[0], pos[1] + i + 1, id);
    hardCells(pos[0], pos[1] - (i + 1), id);
  }
  if (Math.random() < 0.5){
    for (var i = 0; i < (size - 1) / 2 - 1; i++) {
      for (var j = 0; j < (size - 1) / 2 - i ; j++) {
        hardCells(pos[0] - (i + 1), pos[1] - j, id);
        hardCells(pos[0] + (i + 1), pos[1] - j, id);
        hardCells(pos[0] - (i + 1), pos[1] + j, id);
        hardCells(pos[0] + (i + 1), pos[1] + j, id);
      }
    }
  }
  else{
    for (var i = 0; i < (size - 1) / 2; i++) {
      for (var j = 0; j <  (size - 1) / 2 - (i - 1); j++) {
        hardCells(pos[0] - (i + 1), pos[1] - j, id);
        hardCells(pos[0] + (i + 1), pos[1] - j, id);
        hardCells(pos[0] - (i + 1), pos[1] + j, id);
        hardCells(pos[0] + (i + 1), pos[1] + j, id);
      }
    }
  }
}

function hardCells(targetx, targety, id) {
    if (grid[targetx] != undefined)
    {
      if (grid[targetx][targety] != undefined)
      {
          document.getElementById(grid[targetx][targety].id).classList.toggle("hardCell", true);
          grid[targetx][targety].motionDetector = true;
          grid[targetx][targety].motionID = id;
      }
    }
}

function reset(){
  width = 0;
  height = 0;
  state = null;
  cnt = 1;
  grid = [];
  running = false;
  globalx = 0;
  globaly = 0;
  steps = 0;
  startx = 0;
  starty = 0;
  areas = 0;
  globalMotionID = -1;
  globalMotionTime = 0;
  document.getElementById("counter").innerHTML = "0";
  document.getElementById("timer").innerHTML = "0.00";
  document.getElementById("table").innerHTML = "";
}
