import React from "react";
import _ from "lodash";
import Kendra from "aws-sdk/clients/kendra";

import { AdditionalResultAttributeKeys, Relevance } from "../constants";
import { isNullOrUndefined, selectMostRecentUpdatedTimestamp } from "../utils";

import SingleLeftArrow from "./components/SingleLeftArrow";
import SingleRightArrow from "./components/SingleRightArrow";
import ResultTitle from "./components/ResultTitle";
import ResultText from "./components/ResultText";
import ResultFooter from "./components/ResultFooter";

import "../search.scss";

const KENDRA_SUGGESTED_ANSWERS = "Amazon Kendra suggested answers";
const MAX_TOP_ANSWER_LENGTH = 25;

interface TopResultsProps {
  results: Kendra.QueryResultItemList;

  submitFeedback: (
    relevance: Relevance,
    resultItem: Kendra.QueryResultItem
  ) => Promise<void>;
}

interface TopResultsState {
  currentResultIndex: number;
  totalResults: number;
}

export default class TopResults extends React.Component<
  TopResultsProps,
  TopResultsState
> {
  // All results in this component has QueryResultType === "ANSWER"
  state = {
    currentResultIndex: 0,
    totalResults: this.props.results.length
  };

  private updatePreviousResultIndex = () => {
    if (this.state.currentResultIndex === 0) {
      return;
    }

    this.setState(prevState => ({
      currentResultIndex: prevState.currentResultIndex - 1
    }));
  };

  private updateNextResultIndex = () => {
    if (this.state.currentResultIndex === this.state.totalResults - 1) {
      return;
    }

    this.setState(prevState => ({
      currentResultIndex: prevState.currentResultIndex + 1
    }));
  };

  private getTopAnswer = (text: Kendra.TextWithHighlights) => {
    if (text && text.Highlights) {
      for (const highlight of text.Highlights) {
        const length = highlight.EndOffset - highlight.BeginOffset;
        if (
          highlight &&
          highlight.TopAnswer &&
          length < MAX_TOP_ANSWER_LENGTH
        ) {
          return text.Text!.substring(
            highlight.BeginOffset,
            highlight.EndOffset
          );
        }
      }
    }

    return null;
  };

  private renderResults = (result: Kendra.QueryResultItem, idx: number) => {
    const { submitFeedback } = this.props;

    if (!isNullOrUndefined(result)) {
      let attributes = Object();
      if (!isNullOrUndefined(result.DocumentAttributes)) {
        result.DocumentAttributes!.forEach(attribute => {
          attributes[attribute.Key] = attribute.Value;
        });
      }

      let resultAttributes = Object();
      if (!isNullOrUndefined(result.AdditionalAttributes)) {
        result.AdditionalAttributes!.forEach(attribute => {
          resultAttributes[attribute.Key] = attribute.Value;
        });
      }

      const answer = resultAttributes[AdditionalResultAttributeKeys.AnswerText];
      const lastUpdated = selectMostRecentUpdatedTimestamp(attributes);
      const topAnswer = this.getTopAnswer(answer.TextWithHighlightsValue);

      return (
        <React.Fragment key={result.Id}>
          <div className="container-body">
            <ResultTitle
              queryResultItem={result}
              attributes={attributes}
              submitFeedback={submitFeedback}
            />
            {!_.isEmpty(topAnswer) && <h1>{topAnswer}</h1>}
            <ResultText
              text={answer.TextWithHighlightsValue}
              lastUpdated={lastUpdated}
            />
            <ResultFooter
              queryResultItem={result}
              attributes={attributes}
              submitFeedback={submitFeedback}
            />
          </div>
        </React.Fragment>
      );
    } else {
      return null;
    }
  };

  render() {
    const { results } = this.props;
    const resultsToShow = results.map(this.renderResults);

    if (isNullOrUndefined(results) || results.length === 0) {
      return null;
    }

    return (
      <div className="result-container card">
        <div className="card-title">{KENDRA_SUGGESTED_ANSWERS}</div>
        <div className="container-divider" />
        <div className="carousel-relative-wrapper inside-card-result-container">
          <div className="carousel-wrapper">
            <div className="carousel-container">
              <div className="result-item">
                {resultsToShow[this.state.currentResultIndex]}
              </div>

              {resultsToShow.map((res, idx) => (
                <div className="offscreen result-item" key={idx}>
                  {res}
                </div>
              ))}
            </div>
          </div>

          {this.state.currentResultIndex > 0 && (
            <div className="arrow-left">
              <div className="arrow" onClick={this.updatePreviousResultIndex}>
                <SingleLeftArrow />
              </div>
            </div>
          )}

          {this.state.currentResultIndex < this.state.totalResults - 1 && (
            <div className="arrow-right">
              <div className="arrow" onClick={this.updateNextResultIndex}>
                <SingleRightArrow />
              </div>
            </div>
          )}
        </div>

        {this.state.totalResults > 1 && (
          <ul className="kendra-carousel-indicators">
            {[...Array(this.state.totalResults)].map((x, index) => (
              <li
                key={index}
                className={
                  index === this.state.currentResultIndex
                    ? "kendra-carousel-indicator kendra-carousel-indicator--active"
                    : "kendra-carousel-indicator"
                }
              />
            ))}
          </ul>
        )}
      </div>
    );
  }
}