/**
 * @license
 * Copyright 2016 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import '../gr-markdown/gr-markdown';
import {CommentLinks} from '../../../types/common';
import {LitElement, css, html, TemplateResult} from 'lit';
import {customElement, property} from 'lit/decorators.js';
import {getAppContext} from '../../../services/app-context';
import {KnownExperimentId} from '../../../services/flags/flags';

const CODE_MARKER_PATTERN = /^(`{1,3})([^`]+?)\1$/;
const INLINE_PATTERN = /(\[.+?\]\(.+?\)|`[^`]+?`)/;
const EXTRACT_LINK_PATTERN = /\[(.+?)\]\((.+?)\)/;

export type Block = ListBlock | QuoteBlock | Paragraph | CodeBlock | PreBlock;
export interface ListBlock {
  type: 'list';
  items: ListItem[];
}
export interface ListItem {
  spans: InlineItem[];
}

export interface QuoteBlock {
  type: 'quote';
  blocks: Block[];
}
export interface Paragraph {
  type: 'paragraph';
  spans: InlineItem[];
}
export interface CodeBlock {
  type: 'code';
  text: string;
}
export interface PreBlock {
  type: 'pre';
  text: string;
}

export type InlineItem = TextSpan | LinkSpan | CodeSpan;

export interface TextSpan {
  type: 'text';
  text: string;
}

export interface LinkSpan {
  type: 'link';
  text: string;
  url: string;
}

export interface CodeSpan {
  type: 'code';
  text: string;
}

declare global {
  interface HTMLElementTagNameMap {
    'gr-formatted-text': GrFormattedText;
  }
}
@customElement('gr-formatted-text')
export class GrFormattedText extends LitElement {
  @property({type: String})
  content?: string;

  @property({type: Object})
  config?: CommentLinks;

  @property({type: Boolean, reflect: true})
  noTrailingMargin = false;

  private readonly flagsService = getAppContext().flagsService;

  static override get styles() {
    return [
      css`
        :host {
          display: block;
          font-family: var(--font-family);
        }
        a {
          color: var(--link-color);
        }
        p,
        ul,
        code,
        blockquote,
        gr-markdown.pre {
          margin: 0 0 var(--spacing-m) 0;
        }
        p,
        ul,
        code,
        blockquote {
          max-width: var(--gr-formatted-text-prose-max-width, none);
        }
        :host([noTrailingMargin]) p:last-child,
        :host([noTrailingMargin]) ul:last-child,
        :host([noTrailingMargin]) blockquote:last-child,
        :host([noTrailingMargin]) gr-markdown.pre:last-child {
          margin: 0;
        }
        blockquote {
          border-left: 1px solid #aaa;
          padding: 0 var(--spacing-m);
        }
        code {
          display: block;
          /* pre will preserve whitespace and linebreaks but not wrap */
          white-space: pre;
          background-color: var(--background-color-secondary);
          border: 1px solid var(--border-color);
          border-left-width: var(--spacing-s);
          margin: var(--spacing-m) 0;
          padding: var(--spacing-s) var(--spacing-m);
          overflow-x: auto;
        }
        li {
          list-style-type: disc;
          margin-left: var(--spacing-xl);
        }
        .inline-code,
        code {
          font-family: var(--monospace-font-family);
          font-size: var(--font-size-code);
          line-height: var(--line-height-mono);
          background-color: var(--background-color-secondary);
          border: 1px solid var(--border-color);
          padding: 1px var(--spacing-s);
        }
      `,
    ];
  }

  override render() {
    if (!this.content) return;

    if (this.flagsService.isEnabled(KnownExperimentId.RENDER_MARKDOWN)) {
      return html`<gr-markdown
        .markdown=${true}
        .content=${this.content}
      ></gr-markdown>`;
    } else {
      const blocks = this._computeBlocks(this.content);
      return html`${blocks.map(block => this.renderBlock(block))}`;
    }
  }

  /**
   * Given a source string, parse into an array of block objects. Each block
   * has a `type` property which takes any of the following values.
   * * 'paragraph' (Paragraph of regular text)
   * * 'quote' (Block quote.)
   * * 'pre' (Pre-formatted text.)
   * * 'list' (Unordered list.)
   * * 'code' (code blocks.)
   *
   * For blocks of type 'paragraph' there is a list of spans that is the content
   * for that paragraph.
   *
   * For blocks of type 'pre' and 'code' there is a `text`
   * property that maps to a string of the block's content.
   *
   * For blocks of type 'list', there is an `items` property that maps to a
   * list of strings representing the list items.
   *
   * For blocks of type 'quote', there is a `blocks` property that maps to a
   * list of blocks contained in the quote.
   *
   * NOTE: Strings appearing in all block objects are NOT escaped.
   */
  _computeBlocks(content: string): Block[] {
    const result: Block[] = [];
    const lines = content.replace(/[\s\n\r\t]+$/g, '').split('\n');

    for (let i = 0; i < lines.length; i++) {
      if (!lines[i].length) {
        continue;
      }

      if (this.isCodeMarkLine(lines[i])) {
        const startOfCode = i + 1;
        const endOfCode = this.getEndOfSection(
          lines,
          startOfCode,
          line => !this.isCodeMarkLine(line)
        );
        result.push({
          type: 'code',
          // Does not include either of the ``` lines
          text: lines.slice(startOfCode, endOfCode).join('\n'),
        });
        i = endOfCode; // advances past the closing```
        continue;
      }
      if (this.isSingleLineCode(lines[i])) {
        // no guard check as _isSingleLineCode tested on the pattern
        const codeContent = lines[i].match(CODE_MARKER_PATTERN)![2];
        result.push({type: 'code', text: codeContent});
      } else if (this.isList(lines[i])) {
        const endOfList = this.getEndOfSection(lines, i + 1, line =>
          this.isList(line)
        );
        result.push(this.makeList(lines.slice(i, endOfList)));
        i = endOfList - 1;
      } else if (this.isQuote(lines[i])) {
        const endOfQuote = this.getEndOfSection(lines, i + 1, line =>
          this.isQuote(line)
        );
        const blockLines = lines
          .slice(i, endOfQuote)
          .map(l => l.replace(/^[ ]?>[ ]?/, ''));
        result.push({
          type: 'quote',
          blocks: this._computeBlocks(blockLines.join('\n')),
        });
        i = endOfQuote - 1;
      } else if (this.isPreFormat(lines[i])) {
        const endOfPre = this.findEndOfPreBlock(lines, i);
        result.push({
          type: 'pre',
          text: lines.slice(i, endOfPre).join('\n'),
        });
        i = endOfPre - 1;
      } else {
        const endOfRegularLines = this.getEndOfSection(lines, i + 1, line =>
          this.isRegularLine(line)
        );
        result.push({
          type: 'paragraph',
          spans: this.computeInlineItems(
            lines.slice(i, endOfRegularLines).join('\n')
          ),
        });
        i = endOfRegularLines - 1;
      }
    }

    return result;
  }

  private computeInlineItems(content: string): InlineItem[] {
    const result: InlineItem[] = [];
    const textSpans = content.split(INLINE_PATTERN);
    for (let i = 0; i < textSpans.length; ++i) {
      // Because INLINE_PATTERN has a single capturing group, string.split will
      // return strings before and after each match as well as the matched
      // group. These are always interleaved starting with a non-matched string
      // which may be empty.
      if (textSpans[i].length === 0) {
        // No point in processing empty strings.
        continue;
      } else if (i % 2 === 0) {
        // A non-matched string.
        result.push({type: 'text', text: textSpans[i]});
      } else if (textSpans[i].startsWith('`')) {
        result.push({type: 'code', text: textSpans[i].slice(1, -1)});
      } else {
        const m = textSpans[i].match(EXTRACT_LINK_PATTERN);
        if (!m) {
          result.push({type: 'text', text: textSpans[i]});
        } else {
          // eslint-disable-next-line @typescript-eslint/no-unused-vars
          const [_, text, url] = m;
          result.push({type: 'link', text, url});
        }
      }
    }
    return result;
  }

  private getEndOfSection(
    lines: string[],
    startIndex: number,
    sectionPredicate: (line: string) => boolean
  ) {
    const index = lines
      .slice(startIndex)
      .findIndex(line => !sectionPredicate(line));
    return index === -1 ? lines.length : index + startIndex;
  }

  private findEndOfPreBlock(lines: string[], startIndex: number) {
    let lastPreFormat = startIndex;
    for (let i = startIndex + 1; i < lines.length; ++i) {
      const line = lines[i];
      if (this.isPreFormat(line)) {
        lastPreFormat = i;
      } else if (!this.isWhitespaceLine(line) && line.length !== 0) {
        break;
      }
    }
    return lastPreFormat + 1;
  }

  /**
   * Take a block of comment text that contains a list, generate appropriate
   * block objects and append them to the output list.
   *
   * * Item one.
   * * Item two.
   * * item three.
   *
   * TODO(taoalpha): maybe we should also support nested list
   *
   * @param lines The block containing the list.
   */
  private makeList(lines: string[]): Block {
    return {
      type: 'list',
      items: lines.map(line => {
        return {
          spans: this.computeInlineItems(line.substring(1).trim()),
        };
      }),
    };
  }

  private isRegularLine(line: string): boolean {
    return (
      !this.isQuote(line) &&
      !this.isCodeMarkLine(line) &&
      !this.isSingleLineCode(line) &&
      !this.isList(line) &&
      !this.isPreFormat(line)
    );
  }

  private isQuote(line: string): boolean {
    return line.startsWith('> ') || line.startsWith(' > ');
  }

  private isCodeMarkLine(line: string): boolean {
    return /^\s{0,3}```/.test(line);
  }

  private isSingleLineCode(line: string): boolean {
    return CODE_MARKER_PATTERN.test(line);
  }

  private isPreFormat(line: string): boolean {
    return /^(\s{4}|\t)/.test(line) && !this.isWhitespaceLine(line);
  }

  private isList(line: string): boolean {
    return /^[-*] /.test(line);
  }

  private isWhitespaceLine(line: string): boolean {
    return /^\s+$/.test(line);
  }

  private renderInlineText(content: string): TemplateResult {
    return html`<gr-markdown .content=${content}></gr-markdown>`;
  }

  private renderLink(text: string, url: string): TemplateResult {
    return html`<a target="_blank" href=${url}>${text}</a>`;
  }

  private renderInlineCode(text: string): TemplateResult {
    return html`<span class="inline-code">${text}</span>`;
  }

  private renderInlineItem(span: InlineItem): TemplateResult {
    switch (span.type) {
      case 'text':
        return this.renderInlineText(span.text);
      case 'link':
        return this.renderLink(span.text, span.url);
      case 'code':
        return this.renderInlineCode(span.text);
      default:
        return html``;
    }
  }

  private renderListItem(item: ListItem): TemplateResult {
    return html` <li>
      ${item.spans.map(item => this.renderInlineItem(item))}
    </li>`;
  }

  private renderBlock(block: Block): TemplateResult {
    switch (block.type) {
      case 'paragraph':
        return html` <p>
          ${block.spans.map(item => this.renderInlineItem(item))}
        </p>`;
      case 'quote':
        return html`
          <blockquote>
            ${block.blocks.map(subBlock => this.renderBlock(subBlock))}
          </blockquote>
        `;
      case 'code':
        return html`<code>${block.text}</code>`;
      case 'pre':
        return html`<pre><code>${block.text}</code></pre>`;
      case 'list':
        return html`
          <ul>
            ${block.items.map(item => this.renderListItem(item))}
          </ul>
        `;
    }
  }
}
