/**
 * Copyright (c) 2016-present, NDLA.
 *
 * This source code is licensed under the GPLv3 license found in the
 * LICENSE file in the root directory of this source tree.
 *
 */

// Can be removed when updating to jsx-a11y 6.x
/* eslint jsx-a11y/no-noninteractive-element-to-interactive-role: 1 */

import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
import BEMHelper from 'react-bem-helper';
import { Trans } from 'ndla-i18n';
import debounce from 'lodash/debounce';

import { Home, Back, Additional, ChevronRight } from 'ndla-icons/common';
import { Cross } from 'ndla-icons/action';
import { SafeLink, Tooltip } from 'ndla-ui';
import { ModalHeader } from 'ndla-modal';
import Button from 'ndla-button';
import SubtopicLinkList from './SubtopicLinkList';
import { TopicShape } from '../shapes';

import Logo from '../Logo';
import { FilterListPhone } from '../Filter';

const classes = new BEMHelper({
  name: 'topic-menu',
  prefix: 'c-',
});

export const renderAdditionalIcon = (isAdditional, label) => {
  if (isAdditional && label) {
    return (
      <Tooltip
        tooltip={label}
        tooltipContainerClass="c-topic-menu__tooltipContainer">
        <Additional className="c-icon--20" />
      </Tooltip>
    );
  }
  if (isAdditional) {
    return <Additional className="c-icon--20 c-topic-menu__tooltipContainer" />;
  }
  return null;
};

export default class TopicMenu extends Component {
  constructor(props) {
    super(props);
    this.handleClick = this.handleClick.bind(this);
    this.handleBtnKeyPress = this.handleBtnKeyPress.bind(this);
    this.handleSubtopicExpand = this.handleSubtopicExpand.bind(this);
    this.handleOnGoBack = this.handleOnGoBack.bind(this);
    this.setScreenSize = this.setScreenSize.bind(this);
    this.setScreenSizeDebounced = debounce(() => this.setScreenSize(false), 50);

    this.state = {
      isNarrowScreen: false,
      competenceGoalsOpen: false,
    };
  }

  componentDidMount() {
    this.setScreenSize(true);
    window.addEventListener('resize', this.setScreenSizeDebounced);
  }

  componentWillUnmount() {
    this.setScreenSizeDebounced.cancel();
    window.removeEventListener('resize', this.setScreenSizeDebounced);
  }

  setScreenSize(initial = false) {
    const isNarrowScreen =
      (window.innerWidth || document.documentElement.clientWidth) < 768;

    /* eslint react/no-did-mount-set-state: 0 */
    if ((initial && isNarrowScreen) || !initial) {
      this.setState({
        isNarrowScreen,
      });
    }
    /* eslint react/no-did-mount-set-state: 1 */
  }

  handleClick(event, topicId) {
    this.props.onNavigate(topicId, null);
  }

  handleSubtopicExpand(subtopicId, index) {
    this.props.onNavigate(this.props.expandedTopicId, subtopicId, index);
  }

  handleOnGoBack() {
    this.props.onNavigate(
      this.props.expandedSubtopicsId.length ? this.props.expandedTopicId : null,
      null,
    );
  }

  handleBtnKeyPress(event, topicId) {
    if (event.charCode === 32 || event.charCode === 13) {
      // space or enter
      event.preventDefault();
      this.props.onNavigate(topicId, null);
    }
  }

  renderCompentenceGoals(competenceGoalsOpen, t) {
    return (
      <Button
        className={
          this.state.isNarrowScreen
            ? 'c-button c-button--lighter c-topic-menu__competence-open-button'
            : 'c-topic-menu__competence-toggle-button'
        }
        stripped={!this.state.isNarrowScreen}
        onClick={() =>
          this.setState({
            competenceGoalsOpen: !competenceGoalsOpen,
          })
        }>
        {competenceGoalsOpen ? (
          <span>
            {t('competenceGoals.closeCompetenceGoals')} <Cross />
          </span>
        ) : (
          t('competenceGoals.showCompetenceGoals')
        )}
      </Button>
    );
  }

  render() {
    const {
      topics,
      toTopic,
      subjectTitle,
      toSubject,
      close: closeMenu,
      expandedTopicId,
      expandedSubtopicsId,
      filterOptions,
      filterValues,
      onFilterClick,
      resourceToLinkProps,
      hideSearch,
      competenceGoals,
      searchFieldComponent,
      toFrontpage,
      locale,
    } = this.props;
    const { competenceGoalsOpen } = this.state;
    const expandedTopic = topics.find(topic => topic.id === expandedTopicId);

    const currentlyExpandedSubTopics = [];
    if (expandedTopic) {
      let currentSubtopic;
      let foundMatch;
      expandedSubtopicsId.forEach((id, index) => {
        if (index === 0) {
          currentSubtopic = expandedTopic.subtopics.find(
            topic => topic.id === id,
          );
          foundMatch = currentSubtopic ? 0 : undefined;
        } else {
          currentSubtopic = currentSubtopic.subtopics.find(
            topic => topic.id === id,
          );
          foundMatch += currentSubtopic ? 1 : 0;
        }
        if (foundMatch === index) {
          currentlyExpandedSubTopics[index] = currentSubtopic;
        }
      });
    }

    const hasExpandedSubtopics = currentlyExpandedSubTopics.length > 0;
    const subTopicModifiers = ['sub-topic'];

    if (!hasExpandedSubtopics) {
      subTopicModifiers.push('no-border');
    }

    const disableMain = this.state.isNarrowScreen && expandedTopic;
    const disableSubTopic = disableMain && hasExpandedSubtopics;
    const disableHeaderNavigation =
      this.state.isNarrowScreen && competenceGoalsOpen;

    const sliderCounter = !expandedTopicId ? 0 : expandedSubtopicsId.length + 1;

    return (
      <Trans>
        {({ t }) => (
          <nav>
            <ModalHeader modifier={['white', 'menu']}>
              <div {...classes('masthead-left')}>
                <button
                  type="button"
                  {...classes('close-button')}
                  onClick={closeMenu}>
                  <Cross />
                  <span>{t('masthead.menu.close')}</span>
                </button>
              </div>
              <div {...classes('masthead-right')}>
                {!hideSearch && searchFieldComponent}
                <Logo
                  to="#"
                  isBeta={this.props.isBeta}
                  label={t('logo.altText')}
                  locale={locale}
                />
              </div>
            </ModalHeader>
            <div {...classes('content')}>
              <div {...classes('back', 'wide')}>
                <SafeLink {...classes('back-link')} to={toFrontpage()}>
                  <Home {...classes('home-icon', '', 'c-icon--20')} />
                  {t('masthead.menu.subjectOverview')}
                </SafeLink>
              </div>
              <div
                {...classes('back', {
                  'hidden-phone': competenceGoalsOpen,
                  narrow: true,
                })}>
                <SafeLink {...classes('back-link')} to={toFrontpage()}>
                  <Home {...classes('home-icon', '', 'c-icon--20')} />
                  {t('masthead.menu.subjectOverview')}
                </SafeLink>
              </div>
              {!disableMain && (
                <Fragment>
                  {!disableHeaderNavigation && (
                    <div
                      {...classes('subject', {
                        hasFilter:
                          filterOptions &&
                          filterOptions.length > 0 &&
                          !competenceGoalsOpen,
                      })}>
                      <div {...classes('subject__header')}>
                        <h1>
                          <SafeLink to={toSubject()}>
                            {subjectTitle}
                            <ChevronRight />
                          </SafeLink>
                        </h1>
                        {competenceGoals &&
                          !this.state.isNarrowScreen &&
                          this.renderCompentenceGoals(competenceGoalsOpen, t)}
                      </div>
                      {!competenceGoalsOpen &&
                        filterOptions &&
                        filterOptions.length > 1 && (
                          <div {...classes('filter-wrapper')}>
                            <FilterListPhone
                              activeFiltersNarrow
                              alignedGroup
                              options={filterOptions}
                              values={filterValues}
                              onChange={onFilterClick}
                              messages={{
                                useFilter: t('masthead.menu.useFilter'),
                                openFilter: t('masthead.menu.openFilter'),
                                closeFilter: t('masthead.menu.closeFilter'),
                              }}
                              label={`${subjectTitle}:`}
                            />
                          </div>
                        )}
                      {!competenceGoalsOpen && (
                        <div {...classes('back-button-slide-wrapper')}>
                          <button
                            type="button"
                            {...classes(
                              'back-button-slides',
                              `slide-${sliderCounter}`,
                            )}
                            onClick={this.handleOnGoBack}>
                            <Back /> <span>{t('masthead.menu.back')}</span>
                          </button>
                        </div>
                      )}
                    </div>
                  )}
                </Fragment>
              )}
              {competenceGoalsOpen && (
                <div {...classes('competence')}>
                  <button
                    type="button"
                    {...classes(
                      this.state.isNarrowScreen
                        ? 'competence-close-button'
                        : 'competence-close-button',
                    )}
                    onClick={() =>
                      this.setState({
                        competenceGoalsOpen: false,
                      })
                    }>
                    <Back />
                    {t('competenceGoals.competenceGoalsNarrowBackButton')}
                  </button>
                  {competenceGoals}
                </div>
              )}
              {!competenceGoalsOpen && (
                <div
                  {...classes('subject-navigation', `slide-${sliderCounter}`)}>
                  {!disableMain && (
                    <Fragment>
                      <div {...classes('section', 'main')}>
                        <SafeLink
                          to={toSubject()}
                          className={classes('link', 'big').className}>
                          <span {...classes('link-label')}>
                            {t('masthead.menu.goTo')}:
                          </span>
                          <span {...classes('link-target')}>
                            {t('masthead.menu.subjectPage')}
                            <span {...classes('arrow')}>›</span>
                          </span>
                        </SafeLink>
                        <ul {...classes('list')}>
                          {topics.map(topic => {
                            const active = topic.id === expandedTopicId;

                            return (
                              <li
                                {...classes('topic-item', active && 'active')}
                                key={topic.id}>
                                <button
                                  type="button"
                                  {...classes('link')}
                                  onClick={event =>
                                    this.handleClick(event, topic.id)
                                  }
                                  onKeyPress={event =>
                                    this.handleBtnKeyPress(event, topic.id)
                                  }>
                                  <span>
                                    {topic.name}
                                    {renderAdditionalIcon(
                                      topic.additional,
                                      t('resource.additionalTooltip'),
                                    )}
                                  </span>
                                  <ChevronRight />
                                </button>
                              </li>
                            );
                          })}
                        </ul>
                        {competenceGoals &&
                          this.state.isNarrowScreen &&
                          this.renderCompentenceGoals(false, t)}
                      </div>
                    </Fragment>
                  )}
                  {expandedTopic &&
                    !disableSubTopic && (
                      <SubtopicLinkList
                        classes={classes}
                        className={
                          classes('section', subTopicModifiers).className
                        }
                        closeMenu={closeMenu}
                        topic={expandedTopic}
                        backLabel={
                          !hasExpandedSubtopics
                            ? subjectTitle
                            : currentlyExpandedSubTopics[
                                currentlyExpandedSubTopics.length - 1
                              ].name
                        }
                        goToTitle={t('masthead.menu.goTo')}
                        toTopic={toTopic}
                        expandedSubtopicId={
                          currentlyExpandedSubTopics[0] &&
                          currentlyExpandedSubTopics[0].id
                        }
                        onSubtopicExpand={id => {
                          this.handleSubtopicExpand(id, 0);
                        }}
                        onGoBack={this.handleOnGoBack}
                        resourceToLinkProps={resourceToLinkProps}
                        competenceButton={
                          competenceGoals &&
                          this.state.isNarrowScreen &&
                          this.renderCompentenceGoals(false, t)
                        }
                      />
                    )}
                  {currentlyExpandedSubTopics.map((subTopic, index) => (
                    <SubtopicLinkList
                      key={subTopic.id}
                      classes={classes}
                      className={
                        classes('section', ['sub-topic', 'no-border']).className
                      }
                      closeMenu={closeMenu}
                      topic={subTopic}
                      backLabel={
                        index === 0
                          ? this.props.topics.find(
                              topic => topic.id === this.props.expandedTopicId,
                            ).name
                          : currentlyExpandedSubTopics[index - 1].name
                      }
                      toTopic={toTopic}
                      expandedSubtopicId={
                        currentlyExpandedSubTopics[index + 1]
                          ? currentlyExpandedSubTopics[index + 1].id
                          : 'no way'
                      }
                      onSubtopicExpand={id => {
                        this.handleSubtopicExpand(id, index + 1);
                      }}
                      onGoBack={this.handleOnGoBack}
                      resourceToLinkProps={resourceToLinkProps}
                      defaultCount={this.props.defaultCount}
                      competenceButton={
                        competenceGoals &&
                        this.state.isNarrowScreen &&
                        this.renderCompentenceGoals(false, t)
                      }
                    />
                  ))}
                </div>
              )}
            </div>
          </nav>
        )}
      </Trans>
    );
  }
}

TopicMenu.propTypes = {
  topics: PropTypes.arrayOf(TopicShape).isRequired,
  toFrontpage: PropTypes.func.isRequired,
  toTopic: PropTypes.func.isRequired,
  toSubject: PropTypes.func.isRequired,
  close: PropTypes.func,
  defaultCount: PropTypes.number,
  filterOptions: PropTypes.arrayOf(
    PropTypes.shape({
      title: PropTypes.string.isRequired,
      value: PropTypes.string.isRequired,
    }),
  ),
  onFilterClick: PropTypes.func,
  filterValues: PropTypes.arrayOf(PropTypes.string),
  subjectTitle: PropTypes.string.isRequired,
  resourceToLinkProps: PropTypes.func.isRequired,
  onNavigate: PropTypes.func.isRequired,
  expandedTopicId: PropTypes.string,
  expandedSubtopicsId: PropTypes.arrayOf(PropTypes.string).isRequired,
  isBeta: PropTypes.bool,
  hideSearch: PropTypes.bool,
  competenceGoals: PropTypes.node,
  searchFieldComponent: PropTypes.node,
  locale: PropTypes.string,
};

TopicMenu.defaultProps = {
  defaultCount: 12,
};
