<script setup>
const GRID_COLS = 25
const GRID_ROWS = 80

// Palette of swatches
const palette = [
"#172038",
"#253a5e",
"#3c5e8b",
"#4f8fba",
"#73bed3",
"#a4dddb",
"#193024",
"#245938",
"#2b8435",
"#62ac4c",
"#a2dc6e",
"#c5e49b",
"#19332d",
"#25562e",
"#468232",
"#75a743",
"#a8ca58",
"#d0da91",
"#5f6d43",
"#97933a",
"#a9b74c",
"#cfd467",
"#d5dc97",
"#d6dea6",
"#382a28",
"#43322f",
"#564238",
"#715a42",
"#867150",
"#b1a282",
"#4d2b32",
"#7a4841",
"#ad7757",
"#c09473",
"#d7b594",
"#e7d5b3",
"#341c27",
"#602c2c",
"#884b2b",
"#be772b",
"#de9e41",
"#e8c170",
"#241527",
"#411d31",
"#752438",
"#a53030",
"#cf573c",
"#da863e",
"#1e1d39",
"#402751",
"#7a367b",
"#a23e8c",
"#c65197",
"#df84a5",
"#090a14",
"#10141f",
"#151d28",
"#202e37",
"#394a50",
"#577277",
"#819796",
"#a8b5b2",
"#c7cfcc",
"#ebede9"
]

const colorMap = ref({})
const selectedColor = ref(null)
const selectedColorId = ref(null)

const { get, post } = useApi();
const { initSocket, onGridCellPaint, removeGridCellPaintListener } = useSocket();

onMounted(async () => {
  initSocket()

  try {
    const cells = await get(`/grid-cells?minx=${1}&miny=${1}&maxx=${GRID_ROWS}&maxy=${GRID_COLS}`);
    cells.forEach(cell => {
      let key = `${cell.x},${cell.y}`;
      if(cell.color > 0 && cell.color <= palette.length)
        colorMap.value[key] = palette[cell.color - 1];
      else
        colorMap.value[key] = "#00000000"
;    });
  } catch(e) {
    console.error(e);
  }

  onGridCellPaint((data) => {
    const key = `${data.x},${data.y}`;
    if (data.color > 0 && data.color <= palette.length) {
      colorMap.value[key] = palette[data.color - 1];
    } else {
      delete colorMap.value[key];
    }
  });
});

onUnmounted(() => {
  removeGridCellPaintListener();
});

function onCellClick(r, c) {
  if (!selectedColor.value) return
  const key = `${r},${c}`

  colorMap.value[key] = selectedColor.value

  // Send color paint
  post('/grid-cells/paint', {
    x: r,
    y: c,
    color: selectedColorId.value
  })
}

function onCellRightClick(r, c, e) {
  e.preventDefault()
  const key = `${r},${c}`
  delete colorMap.value[key]

  // Send color delete
  post('/grid-cells/paint', {
    x: r,
    y: c,
    color: 0
  })
}

function onSwatchClick(color) {
  selectedColor.value = color;
  selectedColorId.value = palette.indexOf(color) + 1;
}

const gridStyle = computed(() => ({
  display: 'grid',
  gridTemplateColumns: `repeat(${GRID_ROWS}, 1fr)`,
}))
</script>

<template>
  <div class="place-container">
    <div class="palette-row" role="toolbar" aria-label="Color palette">
      <button
        v-for="(color, i) in palette"
        :key="i"
        type="button"
        class="swatch"
        :class="{ active: selectedColor === color }"
        :style="{ backgroundColor: color }"
        :aria-label="`Select color ${color}`"
        @click="onSwatchClick(color)"
      />
    </div>
    <div class="grid-wrapper" :style="gridStyle">
      <div
        v-for="r in GRID_ROWS"
        :key="`row-${r}`"
        class="grid-row"
      >
        <div
          v-for="c in GRID_COLS"
          :key="`${r}-${c}`"
          class="cell"
          :class="{ filled: colorMap[`${r},${c}`] }"
          :style="colorMap[`${r},${c}`] ? { backgroundColor: colorMap[`${r},${c}`] } : {}"
          @click="onCellClick(r, c)"
          @contextmenu="onCellRightClick(r, c, $event)"
        />
      </div>
    </div>
  </div>
</template>

<style lang="scss" scoped>
.place-container {
  width: 100%;
  max-width: 1200px;
  margin: 0 auto;
}

.palette-row {
  display: flex;
  gap: 6px;
  padding: 12px 0;
  flex-wrap: wrap;
}

.swatch {
  width: 28px;
  height: 28px;
  border: none;
  cursor: pointer;
  transition: border-color 0.05s, transform 0.05s;

  &:hover {
    transform: scale(1.15);
  }

  &.active {
    border: 2px solid var(--color-link, #a4dddb);
    box-shadow: 0 0 0 1px var(--color-link, #a4dddb);
  }

  @media (max-width: 600px) {
    width: 28px;
    height: 28px;
  }
}

.grid-wrapper {
  background-color: var(--color-background-line);
  margin-bottom: 20px;
}

.cell {
  aspect-ratio: 1 / 1;
  cursor: pointer;
  background-color: transparent;
  transition: background-color 0.05s steps(1);

  &:hover {
    outline: 1px solid #fff;
  }
}

.filled {
  opacity: 1;
}
</style>
