import * as panzoom from './modules/pan-zoom.js';
import * as gameboard from './modules/gameboard.js';
import * as recordSheet from './modules/record_sheet.js';
import * as mapSelectDialog from './modules/map_select_dialog.js';
import { Observable } from './modules/observable.js';
import { requestResource, build } from './modules/scenario.js';
import { scenarios } from './modules/scenarios.js';

globalThis.svgns = 'http://www.w3.org/2000/svg';

if (window.IS_DEV) {
  const source = new EventSource('/esbuild');
  source.addEventListener('change', () => location.reload());
  // source.addEventListener('message', (e) => console.log(e));
}

const mapPlaceholder = document.querySelector('.map-placeholder'),
  distanceOutput = document.getElementById('status'),
  proneToggle = document.getElementById('toggle-prone-counter'),
  contentVisToggleEl = document.querySelector('#content input[type="checkbox"].visible'),
  fileName = localStorage.getItem('map') || 'scenario-side_show',
  map = scenarios[fileName]?.hashed || `assets/images/${fileName}.svg`,
  fileInputEl = document.querySelector('input[type="file"]'),
  dice = document.querySelectorAll('.die'),
  mapResourceEl = document.querySelector('object'),
  scenarioRequest = requestResource(map),

  d6 = {
    1: 'one',
    2: 'two',
    3: 'three',
    4: 'four',
    5: 'five',
    6: 'six'
  },

  toggleContentVis = (function () {
    document.querySelector('#content').style.minWidth = this.checked ? '' : 0;

    document.querySelectorAll('#content > div').forEach(div => {
      if (this.checked) {
        div.style.display = div.id == 'record-sheet' ? 'flex' : 'block';
      } else {
        div.style.display = 'none';
      }
    });

    localStorage.setItem('content-visibility', this.checked);
  }).bind(contentVisToggleEl);

let scenarioTemplate;

async function buildScenario(req) {
  gameboard.stop();
  recordSheet.stop();

  const svg = scenarioTemplate.querySelector('svg').cloneNode(true);
  document.querySelector('object').contentDocument.querySelector('svg').replaceWith(svg);

  await build(svg, req);

  mapResourceEl.style.opacity = 1;
  mapPlaceholder.style.opacity = 0;

  panzoom.start(svg);
  gameboard.start(svg);
  recordSheet.start(svg.querySelector('.start-locations'), gameboard.getUnits());
}

function updateTurnCounter() {
  const turnCounter = document.getElementById('turn-count');

  if (turnCounter.dataset.update === '1') {
    turnCounter.children.namedItem('count').textContent++;
    turnCounter.dataset.update = '0';
  } else {
    turnCounter.dataset.update = '1';
  }
}

function enableEndTurnButton(allegiance) {
  document
    .querySelector(`button.end-turn:not([data-allegiance="${allegiance}"])`)
    .removeAttribute('disabled');
}

function clearMoveEndedIndicators(records) {
  records.forEach(el => el.classList.remove('movement-ended'));
}

function distance(count = '-') {
  distanceOutput.querySelector('#hex-count').textContent = count;
  distanceOutput.style.display = count === '-' ? 'none' : 'block';
}

// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random#getting_a_random_integer_between_two_values_inclusive
function getRandomIntInclusive(min, max) {
  const minCeiled = Math.ceil(min);
  const maxFloored = Math.floor(max);
  return Math.floor(Math.random() * (maxFloored - minCeiled + 1) + minCeiled); // The maximum is inclusive and the minimum is inclusive
}

// ⚀ ⚁ ⚂ ⚃ ⚄ ⚅
function roll(die) {
  const numsAsWords = Object.values(die);
  return numsAsWords[getRandomIntInclusive(0, numsAsWords.length - 1)];
}

async function load() {
  const svg = this.contentDocument.querySelector('svg'),
    startLocs = svg.querySelector('.start-locations')
    // , scriptEl = this.contentDocument.querySelector('script')
    ;

  scenarioTemplate = this.contentDocument.cloneNode(svg);
  await buildScenario(scenarioRequest);

  this.style.opacity = 1;
  mapPlaceholder.style.opacity = 0;
}

document.querySelectorAll('.end-turn').forEach(el =>
  el.addEventListener('click', ({ target: { dataset: { allegiance: opponent }}}) => {
    const dataSelector = `[data-allegiance="${opponent}"]`,
      opponentRecords = Array.from(document.querySelectorAll(`.soldier-record${dataSelector}`)),
      firstOpponentRecord = opponentRecords.sort((el1, el2) => el1.dataset.number > el2.dataset.number).at(0);

    el.setAttribute('disabled', '');
    updateTurnCounter();
    enableEndTurnButton(opponent);
    clearMoveEndedIndicators(opponentRecords);

    gameboard.clearFiringArcs(opponent);
    Observable.notify('select', firstOpponentRecord);
  })
);

document.querySelectorAll('.set-firing-arc').forEach(el =>
  el.addEventListener('click', gameboard.setFiringArc)
);

document.querySelector('.set-grenade').addEventListener('click', gameboard.setGrenade);

document.querySelectorAll('#toggle-firing-arc-vis input').forEach(el =>
  el.addEventListener('input', gameboard.toggleFiringArcVisibility)
);

document.getElementById('toggle-prone-counter').addEventListener('input', function () {
  const selected = recordSheet.getSelected();
  selected && gameboard.toggleProne();
});

document.querySelectorAll('.end-move').forEach(el =>
  el.addEventListener('click', () => Observable.notify('endmove'))
);

document.querySelector('#fullscreen').addEventListener('click', () => {
  if (!document.fullscreenElement) {
    document.documentElement.requestFullscreen();
  } else if (document.exitFullscreen) {
    document.exitFullscreen();
  }
});

document.querySelector('#download-save').addEventListener('click', e => {
  const data = document.querySelector('object').contentDocument.documentElement.outerHTML;
  const element = document.createElement('a');

  element.setAttribute('download', 'save.svg');
  element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(data));
  // element.style.display = 'none';

  // document.body.appendChild(element);
  element.click();
  // document.body.removeChild(element);
});

document.querySelector('#upload-save').addEventListener('click', () => {
  fileInputEl.click();
});

document.querySelector('input[type="file"]').addEventListener('change', e => {
  const [file] =  fileInputEl.files;
  const reader = new FileReader();

  reader.onload = function () {
    const parser = new DOMParser();
    const doc = parser.parseFromString(reader.result, "image/svg+xml");

    mapResourceEl.addEventListener(
      'transitionend',
      () => buildScenario(doc),
      { once: true }
    );
  };

  mapPlaceholder.style.opacity = 1;
  mapResourceEl.style.opacity = 0;
  reader.readAsText(file);
});

document.querySelector('#roll-dice').addEventListener('click', () => {
  dice.forEach(el => {
    el.classList.remove('roll-in');
    el.classList.add('roll-out');
  });
});

contentVisToggleEl.addEventListener('input', toggleContentVis);
contentVisToggleEl.checked = (localStorage.getItem('content-visibility') !== 'false');
toggleContentVis();

mapSelectDialog
  .init()
  .selectCurrentOptionOnPageLoad()
  .showOnClick()
  .updateValueOnSelection()
  .changeMapOnConfirm(data => {
    const scenarioRequest = requestResource(data);

    mapResourceEl.addEventListener(
      'transitionend',
      () => buildScenario(scenarioRequest),
      { once: true }
    );

    mapPlaceholder.style.opacity = 1;
    mapResourceEl.style.opacity = 0;
  });

mapResourceEl.addEventListener('load', load);

dice.forEach(el => {
  el.classList.add(roll(d6));

  el.addEventListener('animationend', e => {
    if (e.animationName === 'roll-out') {
      el.classList.remove('roll-out');
      el.classList.replace(el.classList.item(1), roll(d6));
      el.classList.add('roll-in');
    }
  });
});

Observable.subscribe('distance', distance);
Observable.subscribe('proneflag', checked => proneToggle.checked = checked);
