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

import 'dart:async';
import 'dart:collection';

import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
import 'package:analysis_server/src/computer/computer_outline.dart';
import 'package:analysis_server/src/lsp/handlers/handlers.dart';
import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
import 'package:analysis_server/src/lsp/mapping.dart';
import 'package:analysis_server/src/protocol_server.dart' show Outline;
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/source/line_info.dart';

// If the client does not provide capabilities.documentSymbol.symbolKind.valueSet
// then we must never send a kind that's not in this list.
final defaultSupportedSymbolKinds = new HashSet<SymbolKind>.of([
  SymbolKind.File,
  SymbolKind.Module,
  SymbolKind.Namespace,
  SymbolKind.Package,
  SymbolKind.Class,
  SymbolKind.Method,
  SymbolKind.Property,
  SymbolKind.Field,
  SymbolKind.Constructor,
  SymbolKind.Enum,
  SymbolKind.Interface,
  SymbolKind.Function,
  SymbolKind.Variable,
  SymbolKind.Constant,
  SymbolKind.Str,
  SymbolKind.Number,
  SymbolKind.Boolean,
  SymbolKind.Array,
]);

class DocumentSymbolHandler extends MessageHandler<DocumentSymbolParams,
    Either2<List<DocumentSymbol>, List<SymbolInformation>>> {
  DocumentSymbolHandler(LspAnalysisServer server) : super(server);
  Method get handlesMessage => Method.textDocument_documentSymbol;

  @override
  DocumentSymbolParams convertParams(Map<String, dynamic> json) =>
      DocumentSymbolParams.fromJson(json);

  Future<ErrorOr<Either2<List<DocumentSymbol>, List<SymbolInformation>>>>
      handle(DocumentSymbolParams params) async {
    final symbolCapabilities =
        server?.clientCapabilities?.textDocument?.documentSymbol;

    final clientSupportedSymbolKinds =
        symbolCapabilities?.symbolKind?.valueSet != null
            ? new HashSet<SymbolKind>.of(symbolCapabilities.symbolKind.valueSet)
            : defaultSupportedSymbolKinds;

    final clientSupportsDocumentSymbol =
        symbolCapabilities?.hierarchicalDocumentSymbolSupport ?? false;

    final path = pathOfDoc(params.textDocument);
    final unit = await path.mapResult(requireResolvedUnit);
    return unit.mapResult((unit) => _getSymbols(clientSupportedSymbolKinds,
        clientSupportsDocumentSymbol, path.result, unit));
  }

  DocumentSymbol _asDocumentSymbol(
    HashSet<SymbolKind> clientSupportedSymbolKinds,
    LineInfo lineInfo,
    Outline outline,
  ) {
    return new DocumentSymbol(
      outline.element.name,
      outline.element.parameters,
      elementKindToSymbolKind(clientSupportedSymbolKinds, outline.element.kind),
      outline.element.isDeprecated,
      toRange(lineInfo, outline.codeOffset, outline.codeLength),
      toRange(lineInfo, outline.element.location.offset,
          outline.element.location.length),
      outline.children
          ?.map((child) =>
              _asDocumentSymbol(clientSupportedSymbolKinds, lineInfo, child))
          ?.toList(),
    );
  }

  SymbolInformation _asSymbolInformation(
    String containerName,
    HashSet<SymbolKind> clientSupportedSymbolKinds,
    String documentUri,
    LineInfo lineInfo,
    Outline outline,
  ) {
    return new SymbolInformation(
      outline.element.name,
      elementKindToSymbolKind(clientSupportedSymbolKinds, outline.element.kind),
      outline.element.isDeprecated,
      new Location(
        documentUri,
        toRange(lineInfo, outline.element.location.offset,
            outline.element.location.length),
      ),
      containerName,
    );
  }

  ErrorOr<Either2<List<DocumentSymbol>, List<SymbolInformation>>> _getSymbols(
    HashSet<SymbolKind> clientSupportedSymbolKinds,
    bool clientSupportsDocumentSymbol,
    String path,
    ResolvedUnitResult unit,
  ) {
    final computer =
        new DartUnitOutlineComputer(path, unit.lineInfo, unit.unit);
    final outline = computer.compute();

    if (clientSupportsDocumentSymbol) {
      // Return a tree of DocumentSymbol only if the client shows explicit support
      // for it.
      return success(
        Either2<List<DocumentSymbol>, List<SymbolInformation>>.t1(
          outline?.children
              ?.map((child) => _asDocumentSymbol(
                  clientSupportedSymbolKinds, unit.lineInfo, child))
              ?.toList(),
        ),
      );
    } else {
      // Otherwise, we need to use the original flat SymbolInformation.
      final allSymbols = <SymbolInformation>[];
      final documentUri = new Uri.file(path).toString();

      // Adds a symbol and it's children recursively, supplying the parent
      // name as required by SymbolInformation.
      addSymbol(Outline outline, {String parentName}) {
        allSymbols.add(_asSymbolInformation(
          parentName,
          clientSupportedSymbolKinds,
          documentUri,
          unit.lineInfo,
          outline,
        ));
        outline.children?.forEach(
          (c) => addSymbol(c, parentName: outline.element.name),
        );
      }

      outline?.children?.forEach(addSymbol);

      return success(
        Either2<List<DocumentSymbol>, List<SymbolInformation>>.t2(allSymbols),
      );
    }
  }
}
