import {MDCTooltip} from '@material/tooltip';

import {createExtBadge} from './common.js';

// Each entry includes the following information in order:
// - ID
// - Codename
// - Color (for the label in the legend)
const kDataKeys = [
  [4, 'recommended', '#34A853'],
  [6, 'replies', '#DADCE0'],
  [5, 'questions', '#77909D'],
];
const kRoles = {
  1: 'bronze',
  2: 'silver',
  3: 'gold',
  4: 'platinum',
  5: 'diamond',
  10: 'community_manager',
  20: 'community_specialist',
  100: 'google_employee',
  30: 'alumnus',
};

export default class PerForumStatsSection {
  constructor(existingChartSection, profile, locale, isCommunityConsole) {
    this.locale = locale;
    this.isCommunityConsole = isCommunityConsole;
    this.parseAndSetData(profile);
    this.buildDOM(existingChartSection);
    if (this.data.length) this.injectChart(this.data[0]?.id);
  }

  parseAndSetData(profile) {
    const forumUserInfos = profile?.[1]?.[7] ?? [];
    const forumTitles = profile?.[1]?.[8] ?? [];

    const forumUserInfoIDs = forumUserInfos.map(ui => ui[1]);
    const forumTitleIDs = forumTitles.map(t => t[1]);
    const intersectionForumIDs =
        forumUserInfoIDs.filter(id => forumTitleIDs.includes(id));

    this.data = [];
    for (const id of intersectionForumIDs) {
      const fui = forumUserInfos.find(ui => ui?.[1] === id)?.[2];
      const numMessages = kDataKeys.reduce((prevVal, key) => {
        if (!fui?.[key[0]]) return prevVal;
        return prevVal + fui[key[0]].reduce((prevVal, userActivity) => {
          return prevVal + (userActivity?.[3] ?? 0);
        }, /* initialValue = */ 0);
      }, /* initialValue = */ 0);
      this.data.push({
        id,
        forumTitle: forumTitles.find(t => t?.[1] === id)?.[2],
        forumUserInfo: fui,
        numMessages,
      });
    }
    this.data.sort((a, b) => {
      // First sort by number of messages
      if (b.numMessages > a.numMessages) return 1;
      if (b.numMessages < a.numMessages) return -1;
      // Then sort by name
      return a.forumTitle.localeCompare(
          b.forumTitle, 'en', {sensitivity: 'base'});
    });
  }

  buildDOM(existingChartSection) {
    let section = document.createElement('div');
    section.classList.add('scTailwindUser_profileUserprofilesection');

    let root = document.createElement('div');
    root.classList.add(
        'scTailwindSharedActivitychartroot',
        'TWPT-scTailwindSharedActivitychartroot');

    let title = document.createElement('h2');
    title.classList.add('scTailwindSharedActivitycharttitle');

    let badge, badgeTooltip;
    if (this.isCommunityConsole) {
      [badge, badgeTooltip] = createExtBadge();
    } else {
      badge = document.createElement('span');
      badge.classList.add('TWPT-badge');

      var badgeImg = document.createElement('img');
      badgeImg.src =
          'https://fonts.gstatic.com/s/i/materialicons/repeat/v6/24px.svg';

      badge.appendChild(badgeImg);
    }

    let titleText = document.createElement('span');
    titleText.textContent =
        chrome.i18n.getMessage('inject_perforumstats_heading');

    title.append(badge, titleText);

    let selector = this.createForumSelector();

    let chartEl = document.createElement('div');
    chartEl.classList.add('scTailwindSharedActivitychartchart');
    chartEl.setAttribute('data-twpt-per-forum-chart', '');

    root.append(title, selector, chartEl);
    section.append(root);
    existingChartSection.after(section);
    if (this.isCommunityConsole) new MDCTooltip(badgeTooltip);
  }

  getAplosData(forumId) {
    let aplosData = [];
    for (const [key, name, color] of kDataKeys) {
      let rawData = this.data.find(f => f.id === forumId)?.forumUserInfo?.[key];
      let data;
      if (!rawData) {
        data = [];
      } else {
        // We're filtering empty strings since in the public forum there a lose
        // conversion takes place and the first element of the array is always
        // null, which breaks the Aplos graph rendering.
        data =
            rawData.map(m => JSON.stringify(Object.values(m))).filter(m => !!m);
      }
      aplosData.push({
        color,
        data,
        label: chrome.i18n.getMessage('inject_perforumstats_chart_' + name),
        name,
      });
    }
    return aplosData;
  }

  getMessagesString(num) {
    if (num == 1) {
      return chrome.i18n.getMessage(
          'inject_perforumstats_nummessages_singular');
    }
    return chrome.i18n.getMessage(
        'inject_perforumstats_nummessages_plural', [num]);
  }

  getForumOptionString(forumTitle, labels) {
    if (labels.length == 0) return forumTitle;
    if (labels.length == 1)
      return chrome.i18n.getMessage(
          'inject_perforumstats_forumoption_1helper', [forumTitle, ...labels]);
    if (labels.length == 2)
      return chrome.i18n.getMessage(
          'inject_perforumstats_forumoption_2helpers', [forumTitle, ...labels]);

    // If labels.length > 3, this is unexpected. Here's a sensible fallback:
    return forumTitle + ' (' + labels.join(', ') + ')';
  }

  createForumSelector() {
    let div = document.createElement('div');
    div.classList.add('TWPT-select-container');

    let select = document.createElement('select');
    let noPostsGroup;
    let noPostsGroupFlag = false;
    for (const forumData of this.data) {
      const hasPosted = forumData.numMessages > 0;

      if (!hasPosted && !noPostsGroupFlag) {
        noPostsGroup = document.createElement('optgroup');
        noPostsGroup.label =
            chrome.i18n.getMessage('inject_perforumstats_optgroup_notposted');
        noPostsGroupFlag = true;
      }

      let additionalLabels = [];
      if (hasPosted)
        additionalLabels.push(this.getMessagesString(forumData.numMessages));
      let role = forumData.forumUserInfo?.[1]?.[3] ?? 0;
      if (role)
        additionalLabels.push(chrome.i18n.getMessage(
            'inject_perforumstats_role_' + kRoles[role]));

      let option = document.createElement('option');
      option.textContent =
          this.getForumOptionString(forumData.forumTitle, additionalLabels);
      option.value = forumData.id;
      if (hasPosted)
        select.append(option);
      else
        noPostsGroup.append(option);
    }
    if (noPostsGroupFlag) select.append(noPostsGroup);
    select.addEventListener('change', e => {
      let forumId = e.target.value;
      this.injectChart(forumId);
    });

    div.append(select);
    return div;
  }

  injectChart(forumId) {
    let data = this.getAplosData(forumId);
    let metadata = {
      activities: [],
      finalMonth: undefined,
      locale: this.locale,
      shouldDisableTransitions: true,
    };
    let chartTitle = chrome.i18n.getMessage('inject_perforumstats_chart_label');
    const message = {
      action: 'renderProfileActivityChart',
      prefix: 'TWPT-extrainfo',
      data,
      metadata,
      chartTitle,
    };
    window.postMessage(message, '*');
  }
}
