<template>
  <div class="container">
    <div class="content">
      <h1 class="title">Generator Labiryntu</h1>

      <div class="input-group">
        <input v-model="seed" @keyup.enter="generateMaze" type="text" class="input"
          placeholder="Wprowadź seed (ziarno)">
        <button @click="generateMaze" class="button" type="button">Generuj</button>
      </div>

      <div v-if="maze.length" class="maze-container">
        <div v-for="(row, y) in maze" :key="y" class="maze-row">
          <div v-for="(cell, x) in row" :key="x" :class="['maze-cell',
            {
              'wall': cell === 1,
              'visited': isVisited(x, y),
              'start': x === 1 && y === 1,
              'end': x === maze[0].length - 3 && y === maze.length - 3,
              'player': x === playerX && y === playerY
            }]">
          </div>
        </div>
      </div>

      <div class="mobile-controls" v-if="isMobile">
        <button @click="moveUp" class="control-button">↑</button>
        <div class="horizontal-controls">
          <button @click="moveLeft" class="control-button">←</button>
          <button @click="moveDown" class="control-button">↓</button>
          <button @click="moveRight" class="control-button">→</button>
        </div>
      </div>

      <div class="step-counter">
        Liczba kroków: {{ stepCount }}
      </div>

      <div v-if="completed">
        <p class="completion-message mt-2">Gratulacje! Przeszedłeś labirynt.</p>
        <p class="completion-message">Chcesz spróbować jeszcze raz?</p>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, Ref, onMounted, watch } from 'vue';

const seed = ref('');
const maze = ref<number[][]>([]);

const playerX = ref(1);
const playerY = ref(1);
const stepCount = ref(0);

const completed = ref(false);
const visitedCells: Ref<Set<string>> = ref(new Set<string>());

const isMobile = ref(window.innerWidth < 640);

const updateIsMobile = () => {
  isMobile.value = window.innerWidth < 640;
};

window.addEventListener('resize', updateIsMobile);

const generateMaze = () => {
  const seedValue = seed.value || Math.random().toString(36).substring(7);
  const rows = 50;
  const cols = 50;

  visitedCells.value = new Set();
  stepCount.value = 0;

  const random = (() => {
    let seed = hash(seedValue);
    return () => {
      seed = (seed * 1103515245 + 12345) & 0x7fffffff;
      return seed / 0x7fffffff;
    };
  })();

  maze.value = Array(rows).fill(0).map(() => Array(cols).fill(1));

  const stack: [number, number][] = [[1, 1]];
  maze.value[1][1] = 0;

  while (stack.length > 0) {
    const [x, y] = stack[stack.length - 1];
    const directions = [[0, -1], [1, 0], [0, 1], [-1, 0]].sort(() => random() - 0.5);

    let moved = false;
    for (const [dx, dy] of directions) {
      const nx = x + dx * 2;
      const ny = y + dy * 2;
      if (nx > 0 && nx < cols - 1 && ny > 0 && ny < rows - 1 && maze.value[ny][nx] === 1) {
        maze.value[ny][nx] = 0;
        maze.value[y + dy][x + dx] = 0;
        stack.push([nx, ny]);
        moved = true;
        break;
      }
    }

    if (!moved)
      stack.pop();
  }

  playerX.value = 1;
  playerY.value = 1;
  completed.value = false;
};

const movePlayer = (e: KeyboardEvent) => {
  if (completed.value) return;

  const key = e.key;
  let newX = playerX.value;
  let newY = playerY.value;

  if (key === 'ArrowUp') newY--;
  else if (key === 'ArrowDown') newY++;
  else if (key === 'ArrowLeft') newX--;
  else if (key === 'ArrowRight') newX++;

  moveTo(newX, newY);
};

const moveTo = (newX: number, newY: number) => {
  if (newX >= 0 && newX < maze.value[0].length && newY >= 0 && newY < maze.value.length && maze.value[newY][newX] === 0) {
    playerX.value = newX;
    playerY.value = newY;
    stepCount.value++;
    visitedCells.value.add(`${newX},${newY}`);

    if (newX === maze.value[0].length - 3 && newY === maze.value.length - 3)
      completed.value = true;
  }
};

const moveUp = () => moveTo(playerX.value, playerY.value - 1);
const moveDown = () => moveTo(playerX.value, playerY.value + 1);
const moveLeft = () => moveTo(playerX.value - 1, playerY.value);
const moveRight = () => moveTo(playerX.value + 1, playerY.value);

const hash = (s: string) => s.split('').reduce((a, b) => (((a << 5) - a) + b.charCodeAt(0)) | 0, 0);

onMounted(() => {
  window.addEventListener('keydown', movePlayer);
  generateMaze();
});

watch(completed, (newValue) => {
  if (newValue)
    window.removeEventListener('keydown', movePlayer);
  else
    window.addEventListener('keydown', movePlayer);
});

const isVisited = (x: number, y: number) => {
  if (
    (x == playerX.value && y == playerY.value) ||
    (x == 1 && y == 1) ||
    (x == maze.value[0].length - 3 && y == maze.value.length - 3)
  )
    return false;
  return visitedCells.value.has(`${x},${y}`);
};
</script>

<style scoped>
.container {
  @apply flex justify-center items-center min-h-screen bg-gray-100 min-w-full p-4;
}

.content {
  @apply bg-white p-4 sm:p-8 rounded-lg shadow-lg max-w-full;
}

.title {
  @apply text-2xl sm:text-3xl font-bold text-center mb-4 sm:mb-6;
}

.input-group {
  @apply flex mb-4;
}

.input {
  @apply flex-grow px-4 py-2 border border-gray-300 rounded-l-md focus:outline-none focus:ring-2 focus:ring-blue-500;
}

.button {
  @apply px-4 py-2 bg-blue-500 text-white rounded-r-md hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-500;
}

.maze-container {
  @apply inline-block border-2 border-black max-w-full overflow-auto;
}

.maze-row {
  @apply flex;
}

.maze-cell {
  @apply w-2 h-2 min-w-0.5 min-h-0.5;
}

.wall {
  @apply bg-black;
}

.player {
  @apply bg-red-500;
}

.start {
  @apply bg-green-500;
}

.end {
  @apply bg-yellow-500;
}

.visited {
  @apply bg-blue-200;
}

.step-counter {
  @apply mt-4 text-center text-base sm:text-lg font-semibold;
}

.completion-message {
  @apply text-center text-base sm:text-lg font-semibold text-green-600;
}

/* Nowe style dla przycisków na urządzeniach mobilnych */
.mobile-controls {
  @apply mt-4 flex flex-col items-center;
}

.horizontal-controls {
  @apply flex mt-2 mb-2;
}

.control-button {
  @apply bg-blue-500 text-white font-bold py-2 px-4 rounded-full m-1;
  @apply hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-500;
}
</style>