// Copyright (c) 2013, 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.

/**
 * A library for extracting the documentation from the various HTML libraries
 * ([dart:html], [dart:svg], [dart:web_audio], [dart:indexed_db]) and saving
 * those documentation comments to a JSON file.
 */

library docs;

import '../../../../sdk/lib/_internal/dartdoc/lib/src/dart2js_mirrors.dart';
import '../../../../pkg/compiler/lib/src/mirrors/source_mirrors.dart';
import '../../../../pkg/compiler/lib/src/mirrors/mirrors_util.dart';
import '../../../../sdk/lib/_internal/dartdoc/lib/dartdoc.dart';
import '../../../../sdk/lib/_internal/dartdoc/lib/src/json_serializer.dart';
import '../../../../utils/apidoc/lib/metadata.dart';
import 'dart:async';
import 'dart:io';

/// The various HTML libraries.
const List<String> HTML_LIBRARY_NAMES = const [
  'dart:html',
  'dart:indexed_db',
  'dart:svg',
  'dart:web_audio',
  'dart:web_gl',
  'dart:web_sql'
];
/**
 * Converts the libraries in [HTML_LIBRARY_NAMES] to a json file at [jsonPath]
 * given the library path at [libUri].
 *
 * The json output looks like:
 *     {
 *       $library_name: {
 *         $interface_name: {
 *           comment: "$comment"
 *           members: {
 *             $member: [
 *               [$comment1line1,
 *                $comment1line2,
 *                ...],
 *               ...
 *             ],
 *             ...
 *           }
 *         },
 *         ...
 *       },
 *       ...
 *     }
 *
 * Completes to true if any errors were encountered, false otherwise.
 */
Future<bool> convert(String libUri, String jsonPath) {
  var paths = <String>[];
  for (var libraryName in HTML_LIBRARY_NAMES) {
    paths.add(libraryName);
  }

  return analyze(paths, libUri, options: ['--preserve-comments'])
      .then((MirrorSystem mirrors) {
    var convertedJson = _generateJsonFromLibraries(mirrors);
    return _exportJsonToFile(convertedJson, jsonPath);
  });
}

Future<bool> _exportJsonToFile(Map convertedJson, String jsonPath) {
  return new Future.sync(() {
    final jsonFile = new File(jsonPath);
    var writeJson = prettySerialize(convertedJson);

    var outputStream = jsonFile.openWrite();
    outputStream.writeln(writeJson);
    outputStream.close();
    return outputStream.done.then((_) => false);
  });
}

Map _generateJsonFromLibraries(MirrorSystem mirrors) {
  var convertedJson = {};

  // Sort the libraries by name (not key).
  var sortedLibraries = new List<LibraryMirror>.from(mirrors.libraries.values
      .where((e) => HTML_LIBRARY_NAMES.indexOf(e.uri.toString()) >= 0))
    ..sort((x, y) => x.uri
        .toString()
        .toUpperCase()
        .compareTo(y.uri.toString().toUpperCase()));

  for (LibraryMirror libMirror in sortedLibraries) {
    print('Extracting documentation from ${libMirror.simpleName}.');

    var libraryJson = {};
    var sortedClasses = _sortAndFilterMirrors(
        classesOf(libMirror.declarations).toList(),
        ignoreDocsEditable: true);

    for (ClassMirror classMirror in sortedClasses) {
      print(' class: $classMirror');
      var classJson = {};
      var sortedMembers =
          _sortAndFilterMirrors(membersOf(classMirror.declarations).toList());

      var membersJson = {};
      for (var memberMirror in sortedMembers) {
        print('  member: $memberMirror');
        var memberDomName = domNames(memberMirror)[0];
        var memberComment = _splitCommentsByNewline(
            computeUntrimmedCommentAsList(memberMirror));

        // Remove interface name from Dom Name.
        if (memberDomName.indexOf('.') >= 0) {
          memberDomName =
              memberDomName.substring(memberDomName.indexOf('.') + 1);
        }

        if (!memberComment.isEmpty) {
          membersJson.putIfAbsent(memberDomName, () => memberComment);
        }
      }

      // Only include the comment if DocsEditable is set.
      var classComment =
          _splitCommentsByNewline(computeUntrimmedCommentAsList(classMirror));
      if (!classComment.isEmpty &&
          findMetadata(classMirror.metadata, 'DocsEditable') != null) {
        classJson.putIfAbsent('comment', () => classComment);
      }
      if (!membersJson.isEmpty) {
        classJson.putIfAbsent('members', () => membersJson);
      }

      if (!classJson.isEmpty) {
        libraryJson.putIfAbsent(domNames(classMirror)[0], () => classJson);
      }
    }

    if (!libraryJson.isEmpty) {
      convertedJson.putIfAbsent(nameOf(libMirror), () => libraryJson);
    }
  }

  return convertedJson;
}

/// Filter out mirrors that are private, or which are not part of this docs
/// process. That is, ones without the DocsEditable annotation.
/// If [ignoreDocsEditable] is true, relax the restriction on @DocsEditable().
/// This is to account for classes that are defined in a template, but whose
/// members are generated.
List<DeclarationMirror> _sortAndFilterMirrors(List<DeclarationMirror> mirrors,
    {ignoreDocsEditable: false}) {
  var filteredMirrors = mirrors
      .where((DeclarationMirror c) =>
          !domNames(c).isEmpty &&
          !displayName(c).startsWith('_') &&
          (!ignoreDocsEditable
              ? (findMetadata(c.metadata, 'DocsEditable') != null)
              : true))
      .toList();

  filteredMirrors.sort((x, y) =>
      domNames(x)[0].toUpperCase().compareTo(domNames(y)[0].toUpperCase()));

  return filteredMirrors;
}

List<String> _splitCommentsByNewline(List<String> comments) {
  var out = [];

  comments.forEach((c) {
    out.addAll(c.split(new RegExp('\n')));
  });

  return out;
}

/// Given the class mirror, returns the names found or an empty list.
List<String> domNames(DeclarationMirror mirror) {
  var domNameMetadata = findMetadata(mirror.metadata, 'DomName');

  if (domNameMetadata != null) {
    var domNames = <String>[];
    var tags = domNameMetadata.getField(#name);
    for (var s in tags.reflectee.split(',')) {
      domNames.add(s.trim());
    }

    if (domNames.length == 1 && domNames[0] == 'none') return <String>[];
    return domNames;
  } else {
    return <String>[];
  }
}
