// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

/// Utility code to convert markdown comments to html.
library dartdoc.markdown_processor;

import 'package:analyzer/src/generated/ast.dart';
import 'package:analyzer/src/generated/element.dart'
    show
        LibraryElement,
        Element,
        ConstructorElement,
        CompilationUnitElement,
        ClassMemberElement,
        TopLevelVariableElement,
        PropertyAccessorElement;
import 'package:html/dom.dart' show Document;
import 'package:html/parser.dart' show parse;
import 'package:markdown/markdown.dart' as md;

import 'src/html_utils.dart' show htmlEscape;
import 'src/model.dart';

final List<md.InlineSyntax> _markdown_syntaxes = [new _InlineCodeSyntax()];

// We don't emit warnings currently: #572.
const bool _emitWarning = false;

String _linkDocReference(String reference, ModelElement element,
    NodeList<CommentReference> commentRefs) {
  String link;
  // support for [new Constructor] and [new Class.namedCtr]
  var refs = reference.split(' ');
  if (refs.length == 2 && refs.first == 'new') {
    link = _getMatchingLink(refs[1], element, commentRefs, isConstructor: true);
  } else {
    link = _getMatchingLink(reference, element, commentRefs);
  }
  if (link != null && link.isNotEmpty) {
    return '<a href="$link">$reference</a>';
  } else {
    if (_emitWarning) {
      print("  warning: unresolved doc reference '$reference' (in $element)");
    }
    return '<code>$reference</code>';
  }
}

// TODO: this is in the wrong place
class Documentation {
  final ModelElement element;
  String _asHtml;
  String _asOneLiner;
  Document _asHtmlDocument;

  Documentation(this.element) {
    _processDocsAsMarkdown();
  }

  String get raw => this.element.documentation;

  String get asHtml => _asHtml;

  Document get asHtmlDocument => _asHtmlDocument;

  String get asOneLiner => _asOneLiner;

  bool get hasMoreThanOneLineDocs => _asHtmlDocument.body.children.length > 1;

  void _processDocsAsMarkdown() {
    String tempHtml = renderMarkdownToHtml(raw, element);
    _asHtmlDocument = parse(tempHtml);
    _asHtmlDocument.querySelectorAll('script').forEach((s) => s.remove());
    _asHtmlDocument.querySelectorAll('pre').forEach((e) {
      e.classes.addAll(['prettyprint', 'lang-dart']);
    });
    _asHtml = _asHtmlDocument.body.innerHtml;

    if (_asHtmlDocument.body.children.isEmpty) {
      _asOneLiner = '';
    } else {
      _asOneLiner = _asHtmlDocument.body.children.first.innerHtml;
    }
  }
}

String renderMarkdownToHtml(String text, [ModelElement element]) {
  md.Node _linkResolver(String name) {
    NodeList<CommentReference> commentRefs = _getCommentRefs(element);
    return new md.Text(_linkDocReference(name, element, commentRefs));
  }

  return md.markdownToHtml(text,
      inlineSyntaxes: _markdown_syntaxes, linkResolver: _linkResolver);
}

class _InlineCodeSyntax extends md.InlineSyntax {
  _InlineCodeSyntax() : super(r'\[:\s?((?:.|\n)*?)\s?:\]');

  @override
  bool onMatch(md.InlineParser parser, Match match) {
    var element = new md.Element.text('code', htmlEscape(match[1]));
    parser.addNode(element);
    return true;
  }
}

const List<String> _oneLinerSkipTags = const ["code", "pre"];

NodeList<CommentReference> _getCommentRefs(ModelElement modelElement) {
  if (modelElement == null) return null;
  if (modelElement.documentation == null && modelElement.canOverride()) {
    var melement = modelElement.overriddenElement;
    if (melement != null &&
        melement.element.computeNode() != null &&
        melement.element.computeNode() is AnnotatedNode) {
      var docComment = (melement.element.computeNode() as AnnotatedNode)
          .documentationComment;
      if (docComment != null) return docComment.references;
      return null;
    }
  }
  if (modelElement.element.computeNode() is AnnotatedNode) {
    if ((modelElement.element.computeNode() as AnnotatedNode)
            .documentationComment !=
        null) {
      return (modelElement.element.computeNode() as AnnotatedNode)
          .documentationComment
          .references;
    }
  } else if (modelElement.element is LibraryElement) {
    // handle anonymous libraries
    if (modelElement.element.computeNode() == null ||
        modelElement.element.computeNode().parent == null) {
      return null;
    }
    var node = modelElement.element.computeNode().parent.parent;
    if (node is AnnotatedNode) {
      if ((node as AnnotatedNode).documentationComment != null) {
        return (node as AnnotatedNode).documentationComment.references;
      }
    }
  }
  return null;
}

/// Returns null if element is a parameter.
String _getMatchingLink(
    String codeRef, ModelElement element, List<CommentReference> commentRefs,
    {bool isConstructor: false}) {
  if (commentRefs == null) return null;

  Element refElement;

  for (CommentReference ref in commentRefs) {
    if (ref.identifier.name == codeRef) {
      bool isConstrElement = ref.identifier.staticElement is ConstructorElement;
      if (isConstructor && isConstrElement ||
          !isConstructor && !isConstrElement) {
        refElement = ref.identifier.staticElement;
        break;
      }
    }
  }

  if (refElement == null) return null;

  if (refElement is PropertyAccessorElement &&
      refElement.enclosingElement is CompilationUnitElement) {
    // yay we found an accessor that wraps a const, but we really
    // want the top-level field itself
    refElement = (refElement as PropertyAccessorElement).variable;
  }

  Library refLibrary = element.package.findLibraryFor(refElement);

  if (refLibrary != null) {
    // Is there a way to pull this from a registry of known elements?
    // Seems like we're creating too many objects this way.
    return new ModelElement.from(refElement, refLibrary).href;
  }
  return null;
}
