import counters from './assets/images/counters.svg';
import mapsheets from './assets/images/mapsheets.svg';

async function loadScript(scenario, svg, script) {
  return new Promise((resolve, reject) => {
    const scriptEl = document.createElementNS("http://www.w3.org/2000/svg", 'script');

    scriptEl.onload = () => {
      console.log(`${script}.js loaded`);
      resolve();
    };

    scriptEl.onerror = () => {
      reject(Error('Script failed to load.'));
    };

    const dataset = scenario.querySelector('script')?.dataset || {};
    Object.entries(dataset).forEach(([k, v]) => scriptEl.dataset[k] = v);

    scriptEl.setAttributeNS(null, 'href', `../../${script}.js`);
    svg.append(scriptEl);
  });
}

export async function requestResource(url) {
  return new Promise((resolve, reject) => {
    const request = new XMLHttpRequest();
    request.open('GET', url, true);
    request.responseType = 'document';

    request.onload = function() {
      if (request.status === 200) {
        resolve(request.response);
      } else {
        reject(Error('Image didn\'t load successfully; error code:' + request.statusText));
      }
    };

    request.onerror = function() {
      reject(Error('There was a network error.'));
    };

    request.send();
  });
}

export async function build(svg, request) {
  const defs = svg.querySelector('defs');
  const gb = svg.querySelector('.gameboard');
  const grid = svg.querySelector('.grid');

  const scenario = await request;
  const startLocs = scenario.querySelector('.start-locations');
  const externalResourceEls = Array.from(scenario.querySelectorAll('use[href*=".svg"'));

  scenario.querySelectorAll('defs > *').forEach(el => defs.append(svg.ownerDocument.importNode(el, true)));

  const refs = externalResourceEls.reduce((acc, el) => {
    const href = el.getAttributeNS(null, 'href');
    const [filename] = href.match(/.+\.svg/);
    const fragmentIdentifier = href.split('.svg').pop();

    (acc[filename] ??= new Set()).add(fragmentIdentifier);
    el.setAttributeNS(null, 'href', fragmentIdentifier);

    return acc;
  }, {});

  const hashedFilenames = {
    'counters.svg': counters,
    'mapsheets.svg': mapsheets
  }

  await Promise.all(
    Object.keys(refs).map(filename => requestResource(hashedFilenames[filename]))
  ).then(result => {
    Object.keys(refs).forEach((filename, index) => {
      const external = result[index];

      refs[filename].forEach(fragmentIdentifier => {
        external
          .querySelectorAll(`${fragmentIdentifier} use`)
          .forEach(el => refs[filename].add(el.getAttributeNS(null, 'href')));
      });

      const refsQuery = [...refs[filename]].join(', ');

      external.querySelectorAll(refsQuery).forEach(node =>
        defs.append(svg.ownerDocument.importNode(node, true))
      );
    });
  });

  //if (startLocs) grid.before(svg.ownerDocument.importNode(startLocs, true));

  const scenarioGrid = scenario.querySelector('.grid');
  const scenarioBuildings = scenario.querySelector('.gameboard .buildings');

  if (scenarioGrid) {
    grid.replaceWith(svg.ownerDocument.importNode(scenarioGrid, true));
  }

  if (scenarioBuildings)
    svg.querySelector('.gameboard .buildings').replaceWith(svg.ownerDocument.importNode(scenarioBuildings, true));

  await loadScript(scenario, svg, 'radial')
  return loadScript(scenario, svg, 'map');
}
