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'],
  [7, 'communityvideos', '#F4511E'],
];
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, '*');
  }
}
