'use strict';

import { StaticData, View } from './types';

declare function action_button(action: string, text: string): void;
// declare function register_action(element: HTMLElement, type: string, s: number): void;
declare function send_action(action: string, text: string): boolean;
declare const data: StaticData;
declare const view: View;

/* global view, player, send_action, action_button */

const BONUSES_COUNT = 2;
// const PIECE_COUNT = 32;
const CARD_COUNT = 109;
const GLORY_COUNT = 9;
const medallionS_COUNT = 9;
const STANDEES_COUNT = 5;
const TRACK_COUNT = 5;
const TRACK_LENGTH = 11;
const FACTIONS = ['a', 'c', 'm'];
// const ROLES = ['Anarchist', 'Communist', 'Moderate'];

const ui = {
  bag_of_glory: document.getElementById('bag_of_glory'),
  map: document.getElementById('map'),
  medallions_container: document.getElementById('medallions'),
  markers: document.getElementById('markers'),
  fronts: {
    a: {
      front: document.getElementById('aragon_front'),
      value: document.querySelector('#aragon_front .value'),
      contributions: document.querySelector('#aragon_front .contributions'),
    },
    m: {
      front: document.getElementById('madrid_front'),
      value: document.querySelector('#madrid_front .value'),
      contributions: document.querySelector('#madrid_front .contributions'),
    },
    n: {
      front: document.getElementById('northern_front'),
      value: document.querySelector('#northern_front .value'),
      contributions: document.querySelector('#northern_front .contributions'),
    },
    s: {
      front: document.getElementById('southern_front'),
      value: document.querySelector('#southern_front .value'),
      contributions: document.querySelector('#southern_front .contributions'),
    },
  },
  glory_container: document.getElementById('glory'),
  hand: document.getElementById('hand'),
  player_area: document.getElementById('player_area'),
  current_events: document.getElementById('current_events'),
  roles: {
    a: {
      hero_points: document.querySelector('#role_Anarchist .role_stat'),
      medallions: document.querySelector('#role_Anarchist .role_medallions'),
    },
    c: {
      hero_points: document.querySelector('#role_Communist .role_stat'),
      medallions: document.querySelector('#role_Communist .role_medallions'),
    },
    m: {
      hero_points: document.querySelector('#role_Moderate .role_stat'),
      medallions: document.querySelector('#role_Moderate .role_medallions'),
    },
    pool: {
      hero_points: document.getElementById('pool_hero_points'),
    },
    Anarchist: document.getElementById('role_Anarchist'),
    Communist: document.getElementById('role_Communist'),
    Moderate: document.getElementById('role_Moderate'),
    container: document.getElementById('roles'),
  },
  player_area_tabs: {
    hand_tab: document.getElementById('hand_tab'),
    deck_tab: document.getElementById('deck_tab'),
    discard_tab: document.getElementById('discard_tab'),
    trash_tab: document.getElementById('trash_tab'),
  },
  player_area_cards: {
    hand: document.getElementById('hand'),
    deck: document.getElementById('deck'),
    discard: document.getElementById('discard'),
    trash: document.getElementById('trash'),
  },
  player_areas: {
    container: document.getElementById('player_areas'),
    Anarchist: document.getElementById('player_area_Anarchist'),
    Communist: document.getElementById('player_area_Communist'),
    Moderate: document.getElementById('player_area_Moderate'),
  },
  selectable_cards: document.getElementById('selectable_cards'),
  tableaus: {
    a: document.getElementById('tableau_a'),
    c: document.getElementById('tableau_c'),
    m: document.getElementById('tableau_m'),
  },
  tracks: document.getElementById('tracks'),
  hero_points: document.querySelector('#role_Anarchist .role_stat'),
  turn_info: document.getElementById('turn_info'),
  turn_info_card: document.getElementById('turn_info_card'),
  year: document.getElementById('year'),
  blank_markers: [],
  bonuses: [],
  // fronts: {},
  tokens_on_front: {},
  // front_values: {},
  glory: [],
  initiative_token: undefined,
  medallions: [],
  spaces: [],
  standees: [],
  pieces: [],
  cards: [],
};

let action_register = [];

const LAYOUT_BONUSES = [
  [435, 481],
  [493, 481],
];

const LAYOUT_CURRENT_EVENTS = [
  [172, 648],
  [309, 648],
  [445, 648],
  [584, 648],
];

const LAYOUT_GLORY = [
  [801, 647],
  [860, 647],
  [897, 647],
  [848, 718],
  [775, 771],
  [812, 771],
  [849, 771],
  [885, 771],
  [922, 771],
];

const LAYOUT_medallionS = [
  [364, 556],
  [415, 556],
  [466, 556],
  [517, 556],
  [568, 556],
];

const LAYOUT_TRACKS = [
  [
    [581, 46],
    [618, 46],
    [655, 46],
    [691, 46],
    [728, 46],
    [765, 46],
    [801, 46],
    [838, 46],
    [874, 46],
    [911, 46],
    [948, 46],
  ],
  [
    [581, 156],
    [618, 156],
    [655, 156],
    [691, 156],
    [728, 156],
    [765, 156],
    [801, 156],
    [838, 156],
    [874, 156],
    [911, 156],
    [948, 156],
  ],
  [
    [581, 267],
    [618, 267],
    [655, 267],
    [691, 267],
    [728, 267],
    [765, 267],
    [801, 267],
    [838, 267],
    [874, 267],
    [911, 267],
    [948, 267],
  ],
  [
    [581, 378],
    [618, 378],
    [655, 378],
    [691, 378],
    [728, 378],
    [765, 378],
    [801, 378],
    [838, 378],
    [874, 378],
    [911, 378],
    [948, 378],
  ],
  [
    [581, 489],
    [618, 489],
    [655, 489],
    [691, 489],
    [728, 489],
    [765, 489],
    [801, 489],
    [838, 489],
    [874, 489],
    [911, 489],
    [948, 489],
  ],
];

// @ts-ignore
// (function build_map() {
//   data.fronts.forEach((front) => {
//     const { id, top, left } = front;
//     const element = (ui.fronts[front.id] = document.createElement('div'));
//     element.classList.add('front');
//     element.style.left = `${left}px`;
//     element.style.top = `${top}px`;
//     element.setAttribute('data-front-id', `${id}`);
//     ui.map.appendChild(element);
//     register_action(element, 'front', id);

//     // Contribution tokens

//     // Value of front
//     const front_value_element = (ui.front_values[front.id] =
//       document.createElement('span'));
//     front_value_element.classList.add('value');
//     element.appendChild(front_value_element);
//   });
// })();

function register_action(
  e: HTMLElement & { my_action?: string; my_id?: string | number },
  action: string,
  id: string | number
) {
  e.my_action = action;
  e.my_id = id;
  e.onmousedown = on_click_action;
  action_register.push(e);
}

function on_click_action(evt) {
  if (evt.button === 0)
    if (send_action(evt.target.my_action, evt.target.my_id))
      evt.stopPropagation();
}

function on_click_tab(evt) {
  evt.stopPropagation();
  const { id } = evt.target as HTMLElement;

  Object.entries(ui.player_area_tabs).forEach(([tab, elt]) => {
    const cards_area = ui.player_area_cards[tab.split('_')[0]];
    if (tab === id) {
      elt.setAttribute('data-active', 'active');
      cards_area.setAttribute('data-active', 'active');
    } else {
      elt.setAttribute('data-active', 'inactive');
      cards_area.setAttribute('data-active', 'inactive');
    }
  });
}

function is_action(action, arg) {
  if (arg === undefined) return !!(view.actions && view.actions[action] === 1);
  return !!(
    view.actions &&
    view.actions[action] &&
    view.actions[action].includes(arg)
  );
}

let on_init_once = false;

function on_init() {
  if (on_init_once) return;
  on_init_once = true;

  Object.values(ui.player_area_tabs).forEach((element) => {
    element.addEventListener('click', on_click_tab);
  });

  // Reorder tableaus and roles based on player order
  for (const player of view.player_order) {
    ui.player_areas.container.insertAdjacentElement(
      'beforeend',
      ui.player_areas[player]
    );
    ui.roles.container.insertAdjacentElement('beforeend', ui.roles[player]);
  }
  ui.roles.container.insertAdjacentElement('beforeend', ui.turn_info);

  if (view.current === 'Observer') {
    ui.player_area.style.display = 'none';
  } else {
    document
      .getElementById('player_area_header')
      .setAttribute('data-faction-id', view.current_player_faction);
  }

  // Create blank_markers
  for (let t = 0; t < TRACK_COUNT; ++t) {
    for (let s = 0; s < TRACK_LENGTH; ++s) {
      const bm = t * 11 + s;
      let e = (ui.blank_markers[bm] = document.createElement('div'));
      e.className = 'blank_marker';
      register_action(e, 'blank_marker', bm);
    }
  }

  // create bonus markers
  for (let b = 0; b < BONUSES_COUNT; ++b) {
    let e = (ui.bonuses[b] = document.createElement('div'));
    e.className = 'bonus';
    e.setAttribute('data-bonus-id', '' + b);
    e.style.left = LAYOUT_BONUSES[b][0] + 'px';
    e.style.top = LAYOUT_BONUSES[b][1] + 'px';
    LAYOUT_BONUSES;
    register_action(e, 'bonus', b);
    ui.map.appendChild(ui.bonuses[b]);
  }

  // Create glory
  for (let g = 0; g < GLORY_COUNT; ++g) {
    let e = (ui.glory[g] = document.createElement('div'));
    e.className = 'faction_token';
    ui.glory_container.appendChild(ui.glory[g]);
    e.style.left = LAYOUT_GLORY[g][0] + 'px';
    e.style.top = LAYOUT_GLORY[g][1] + 'px';
  }

  // create track medallions
  for (let m = 0; m < medallionS_COUNT; ++m) {
    let e = (ui.medallions[m] = document.createElement('div'));
    e.className = 'medallion';
    e.setAttribute('data-medallion-id', '' + m);
    register_action(e, 'medallion', m);
  }

  // create track standees
  for (let s = 0; s < STANDEES_COUNT; ++s) {
    let e = (ui.standees[s] = document.createElement('div'));
    e.className = 'standee';
    e.setAttribute('data-standee-id', '' + s);
    register_action(e, 'standee', s);
    ui.tracks.appendChild(ui.standees[s]);
  }

  // create card elements
  for (let c = 1; c < CARD_COUNT; ++c) {
    let e = (ui.cards[c] = document.createElement('div'));
    e.className = 'card';
    e.setAttribute('data-card-id', '' + data.cards[c].id);
    register_action(e, 'card', c);
  }

  // create initiative marker
  let e = (ui.initiative_token = document.createElement('div'));
  e.className = 'initiative_token';

  // create tokens to add to fronts
  data.fronts.forEach((front) => {
    ui.tokens_on_front[front.id] = {};
    FACTIONS.forEach((faction_id) => {
      let e = (ui.tokens_on_front[front.id][faction_id] =
        document.createElement('div'));
      e.className = 'faction_token';
      e.setAttribute('data-faction-id', faction_id);
    });
  });

  Object.keys(ui.fronts).forEach((front_id) => {
    register_action(ui.fronts[front_id].front, 'front', front_id);
  });
}

function place_cards(e: HTMLElement, cards: number[]) {
  e.replaceChildren();
  for (let c of cards) {
    ui.cards[c].classList.remove('selected');
    e.appendChild(ui.cards[c]);
    if (view.selected_cards.includes(c)) {
      ui.cards[c].classList.add('selected');
    }
  }
}

// @ts-ignore
function on_update() {
  console.log('on_update', view);
  on_init();

  for (let key of Object.keys(view.hero_points)) {
    ui.roles[key].hero_points.replaceChildren(
      `Hero Points: ${view.hero_points[key]}`
    );
  }
  ui.bag_of_glory.replaceChildren(`Bag of Glory: ${view.bag_of_glory_count}`);

  // for (let s = 0; s < SPACE_COUNT; ++s) ui.spaces[s].replaceChildren();

  // for (let p = 0; p < PIECE_COUNT; ++p) {
  //   let s = view.location[p];
  //   ui.spaces[s].appendChild(ui.pieces[p]);
  // }
  ui.current_events.replaceChildren();
  for (let i = 0; i < view.current_events.length; i++) {
    const cardId = view.current_events[i];
    ui.current_events.appendChild(ui.cards[cardId]);
    ui.cards[cardId].classList.add('event');
    ui.cards[cardId].style.left = LAYOUT_CURRENT_EVENTS[i][0] + 'px';
    ui.cards[cardId].style.top = LAYOUT_CURRENT_EVENTS[i][1] + 'px';
  }

  ui.markers.replaceChildren();
  for (let bm of view.triggered_track_effects) {
    const s = bm % 11;
    const t = Math.floor(bm / 11);
    ui.markers.appendChild(ui.blank_markers[bm]);
    ui.blank_markers[bm].style.left = LAYOUT_TRACKS[t][s][0] + 'px';
    ui.blank_markers[bm].style.top = LAYOUT_TRACKS[t][s][1] + 'px';
  }

  for (let bonus_id of Object.keys(view.bonuses)) {
    ui.bonuses[bonus_id].setAttribute(
      'data-bonus-on',
      view.bonuses[bonus_id] + 0
    );
  }

  place_cards(ui.hand, view.hand);
  ui.player_area_tabs.hand_tab.replaceChildren(`Hand (${view.hand.length})`);
  place_cards(ui.player_area_cards.deck, view.deck);
  ui.player_area_tabs.deck_tab.replaceChildren(`Deck (${view.deck.length})`);
  place_cards(ui.player_area_cards.discard, view.discard);
  ui.player_area_tabs.discard_tab.replaceChildren(`Discard (${view.discard.length})`);
  place_cards(ui.player_area_cards.trash, view.trash);
  ui.player_area_tabs.trash_tab.replaceChildren(`Trash (${view.trash.length})`);
  
  place_cards(ui.selectable_cards, view.selectable_cards);

  for (let faction_id of FACTIONS) {
    place_cards(ui.tableaus[faction_id], view.tableaus[faction_id]);
  }

  for (let i = 0; i < view.tracks.length; ++i) {
    // ui.tracks.appendChild(ui.standees[i]);
    ui.standees[i].style.left = LAYOUT_TRACKS[i][view.tracks[i]][0] + 'px';
    ui.standees[i].style.top = LAYOUT_TRACKS[i][view.tracks[i]][1] + 'px';
  }

  for (let front_id of Object.keys(view.fronts)) {
    const front_data = view.fronts[front_id];
    // ui.fronts[front_id].value.replaceChildren(front_data.value);
    ui.fronts[front_id].value.replaceChildren(
      front_data.status !== null ? front_data.status : front_data.value
    );
    ui.fronts[front_id].contributions.replaceChildren();
    for (let faction_id of front_data.contributions) {
      ui.fronts[front_id].contributions.appendChild(
        ui.tokens_on_front[front_id][faction_id]
      );
    }
  }

  ui.medallions_container.replaceChildren();
  for (let i = 0; i < view.medallions.pool.length; ++i) {
    if (view.medallions.pool[i] !== null) {
      const id = view.medallions.pool[i];
      ui.medallions[id].style.left = LAYOUT_medallionS[i][0] + 'px';
      ui.medallions[id].style.top = LAYOUT_medallionS[i][1] + 'px';
      ui.medallions_container.appendChild(ui.medallions[id]);
    }
  }
  for (let f of FACTIONS) {
    ui.roles[f].medallions.replaceChildren();
    for (let m of view.medallions[f]) {
      ui.roles[f].medallions.appendChild(ui.medallions[m]);
    }
  }
  ui.roles[view.initiative].medallions.appendChild(ui.initiative_token);
  ui.initiative_token.setAttribute('data-year', view.year);

  if (view.played_card === null) {
    ui.turn_info.style.display = 'none';
  } else {
    ui.turn_info.style.display = '';
    ui.turn_info_card.setAttribute('data-card-id', view.played_card + '');
  }

  Object.values(ui.glory).forEach((elt: HTMLElement) => elt.removeAttribute('data-faction-id'));
  for (let g = 0; g < view.glory.length; ++g) {
    ui.glory[g].setAttribute('data-faction-id', view.glory[g]);
  }

  for (let e of action_register)
    e.classList.toggle('action', is_action(e.my_action, e.my_id));

  ui.year.replaceChildren(`Year ${view.year}`);

  action_button('add_to_front', '+1 to a Front');
  action_button('d_liberty', 'Decrease Liberty');
  action_button('soviet_support', 'Soviet Support');
  action_button('collectivization', 'Collectivization');

  action_button('d_collectivization', 'Decrease Collectivization');
  action_button('d_foreign_aid', 'Decrease Foreign Aid');
  action_button('d_government', 'Decrease Government');

  action_button('d_soviet_support', 'Decrease Soviet Support');

  action_button('foreign_aid', 'Foreign Aid');
  action_button('government', 'Government');
  action_button('liberty', 'Liberty');
  action_button('government_to_center', 'Government towards center');

  action_button('teamwork_on', 'Teamwork Bonus On');
  action_button('Anarchist', 'Anarchist');
  action_button('Communist', 'Communist');
  action_button('Moderate', 'Moderate');
  action_button('gain_hp', 'Gain Hero Points');
  action_button('lose_hp', 'Lose Hero Points');
  action_button('draw_card', 'Draw a card');
  action_button('draw_cards', 'Draw cards');
  // action_button('draw_card', 'Draw card');
  action_button('play_to_tableau', 'Play card to Tableau');
  action_button('play_for_event', 'Play card for Event');
  action_button('use_ap', 'Use Action Points');
  action_button('use_morale_bonus', 'Use Morale Bonus');

  action_button('move_track', 'Move a Track');
  action_button('turn_on_bonus', 'Turn on a Bonus');

  action_button('add_glory', 'Add to Bag of Glory');
  action_button('draw_glory', 'Draw from Bag of Glory');
  action_button('up', 'Up');
  action_button('down', 'Down');
  action_button('next', 'Next');
  action_button('remove_blank_marker', 'Remove Blank marker');
  action_button('confirm', 'Confirm');
  action_button('yes', 'Yes');
  action_button('no', 'No');
  action_button('skip', 'Skip');
  action_button('spend_hp', 'Spend Hero Points');
  action_button('use_momentum', 'Play second card (Momentum)');
  action_button('done', 'Done');
  action_button('end_turn', 'End turn');
  action_button('undo', 'Undo');
}

const IMG_FTA = '<span class="faction_token" data-faction-id="a"></span>';
const IMG_FTC = '<span class="faction_token" data-faction-id="c"></span>';
const IMG_FTM = '<span class="faction_token" data-faction-id="m"></span>';

// @ts-ignore
function on_log(text) {
  let p = document.createElement('div');

  if (text.match(/^>>/)) {
    text = text.substring(2);
    p.className = 'ii';
  }

  if (text.match(/^>/)) {
    text = text.substring(1);
    p.className = 'i';
  }

  // text = text.replace(/&/g, '&amp;');
  // text = text.replace(/</g, '&lt;');
  // text = text.replace(/>/g, '&gt;');
  // text = text.replace(/C(\d+)/g, sub_card_name)
  // text = text.replace(/S(\d+)/g, sub_space_name)
  // text = text.replace(/U(\d+)/g, sub_unit_name)

  // TODO dice icons
  // text = text.replace(/\bD\d\b/g, sub_icon)

  if (text.match(/^\.h1/)) {
    text = text.substring(4);
    p.className = 'h1';
  } else if (text.match(/^\.h2\.Moderate/)) {
    text = text.substring(13);
    p.className = 'h2 moderate';
  } else if (text.match(/^\.h2\.Anarchist/)) {
    text = text.substring(14);
    p.className = 'h2 anarchist';
  } else if (text.match(/^\.h2\.Communist/)) {
    text = text.substring(14);
    p.className = 'h2 communist';
  } else if (text.match(/^\.h2\.fascist/)) {
    text = text.substring(11);
    p.className = 'h2 fascist';
  } else if (text.match(/^\.h2\.glory/)) {
    text = text.substring(9);
    p.className = 'h2 glory';
  } else if (text.match(/^\.h2/)) {
    text = text.substring(4);
    p.className = 'h2';
  } else if (text.match(/^\.h3/)) {
    text = text.substring(4);
    p.className = 'h3';
  }

  text = text.replace(/<fta>/g, IMG_FTA)
	text = text.replace(/<ftc>/g, IMG_FTC)
	text = text.replace(/<ftm>/g, IMG_FTM)

  p.innerHTML = text;
  return p;
}