// 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.

import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/src/summary/format.dart';
import 'package:analyzer/src/summary/idl.dart';

/**
 * Compute the public namespace portion of the summary for the given [unit],
 * which is presumed to be an unresolved AST.
 */
UnlinkedPublicNamespaceBuilder computePublicNamespace(CompilationUnit unit) {
  _PublicNamespaceVisitor visitor = new _PublicNamespaceVisitor();
  unit.accept(visitor);
  return new UnlinkedPublicNamespaceBuilder(
      names: visitor.names, exports: visitor.exports, parts: visitor.parts);
}

/**
 * Serialize a [Configuration] into a [UnlinkedConfigurationBuilder].
 */
UnlinkedConfigurationBuilder serializeConfiguration(
    Configuration configuration) {
  return new UnlinkedConfigurationBuilder(
      name: configuration.name.components.map((i) => i.name).join('.'),
      value: configuration.value?.stringValue ?? 'true',
      uri: configuration.uri.stringValue);
}

class _CombinatorEncoder extends SimpleAstVisitor<UnlinkedCombinatorBuilder> {
  _CombinatorEncoder();

  List<String> encodeNames(NodeList<SimpleIdentifier> names) =>
      names.map((SimpleIdentifier id) => id.name).toList();

  @override
  UnlinkedCombinatorBuilder visitHideCombinator(HideCombinator node) {
    return new UnlinkedCombinatorBuilder(hides: encodeNames(node.hiddenNames));
  }

  @override
  UnlinkedCombinatorBuilder visitShowCombinator(ShowCombinator node) {
    return new UnlinkedCombinatorBuilder(
        shows: encodeNames(node.shownNames),
        offset: node.offset,
        end: node.end);
  }
}

class _PublicNamespaceVisitor extends RecursiveAstVisitor {
  final List<UnlinkedPublicNameBuilder> names = <UnlinkedPublicNameBuilder>[];
  final List<UnlinkedExportPublicBuilder> exports =
      <UnlinkedExportPublicBuilder>[];
  final List<String> parts = <String>[];

  _PublicNamespaceVisitor();

  UnlinkedPublicNameBuilder addNameIfPublic(
      String name, ReferenceKind kind, int numTypeParameters) {
    if (isPublic(name)) {
      UnlinkedPublicNameBuilder b = new UnlinkedPublicNameBuilder(
          name: name, kind: kind, numTypeParameters: numTypeParameters);
      names.add(b);
      return b;
    }
    return null;
  }

  bool isPublic(String name) => !name.startsWith('_');

  @override
  visitClassDeclaration(ClassDeclaration node) {
    UnlinkedPublicNameBuilder cls = addNameIfPublic(
        node.name.name,
        ReferenceKind.classOrEnum,
        node.typeParameters?.typeParameters?.length ?? 0);
    if (cls != null) {
      _addClassMembers(cls, node.members);
    }
  }

  @override
  visitClassTypeAlias(ClassTypeAlias node) {
    addNameIfPublic(node.name.name, ReferenceKind.classOrEnum,
        node.typeParameters?.typeParameters?.length ?? 0);
  }

  @override
  visitEnumDeclaration(EnumDeclaration node) {
    UnlinkedPublicNameBuilder enm =
        addNameIfPublic(node.name.name, ReferenceKind.classOrEnum, 0);
    if (enm != null) {
      enm.members.add(new UnlinkedPublicNameBuilder(
          name: 'values',
          kind: ReferenceKind.propertyAccessor,
          numTypeParameters: 0));
      for (EnumConstantDeclaration enumConstant in node.constants) {
        String name = enumConstant.name.name;
        if (isPublic(name)) {
          enm.members.add(new UnlinkedPublicNameBuilder(
              name: name,
              kind: ReferenceKind.propertyAccessor,
              numTypeParameters: 0));
        }
      }
    }
  }

  @override
  visitExportDirective(ExportDirective node) {
    exports.add(new UnlinkedExportPublicBuilder(
        uri: node.uri.stringValue,
        combinators: node.combinators
            .map((Combinator c) => c.accept(new _CombinatorEncoder()))
            .toList(),
        configurations:
            node.configurations.map(serializeConfiguration).toList()));
  }

  @override
  visitFunctionDeclaration(FunctionDeclaration node) {
    String name = node.name.name;
    if (node.isSetter) {
      name += '=';
    }
    addNameIfPublic(
        name,
        node.isGetter || node.isSetter
            ? ReferenceKind.topLevelPropertyAccessor
            : ReferenceKind.topLevelFunction,
        node.functionExpression.typeParameters?.typeParameters?.length ?? 0);
  }

  @override
  visitFunctionTypeAlias(FunctionTypeAlias node) {
    addNameIfPublic(node.name.name, ReferenceKind.typedef,
        node.typeParameters?.typeParameters?.length ?? 0);
  }

  @override
  visitGenericTypeAlias(GenericTypeAlias node) {
    addNameIfPublic(node.name.name, ReferenceKind.genericFunctionTypedef,
        node.typeParameters?.typeParameters?.length ?? 0);
  }

  @override
  visitMixinDeclaration(MixinDeclaration node) {
    UnlinkedPublicNameBuilder mixin = addNameIfPublic(
        node.name.name,
        ReferenceKind.classOrEnum,
        node.typeParameters?.typeParameters?.length ?? 0);
    if (mixin != null) {
      _addClassMembers(mixin, node.members);
    }
  }

  @override
  visitPartDirective(PartDirective node) {
    parts.add(node.uri.stringValue ?? '');
  }

  @override
  visitVariableDeclaration(VariableDeclaration node) {
    String name = node.name.name;
    addNameIfPublic(name, ReferenceKind.topLevelPropertyAccessor, 0);
    if (!node.isFinal && !node.isConst) {
      addNameIfPublic('$name=', ReferenceKind.topLevelPropertyAccessor, 0);
    }
  }

  void _addClassMembers(
      UnlinkedPublicNameBuilder builder, List<ClassMember> members) {
    for (ClassMember member in members) {
      if (member is FieldDeclaration && member.isStatic) {
        for (VariableDeclaration field in member.fields.variables) {
          String name = field.name.name;
          if (isPublic(name)) {
            builder.members.add(new UnlinkedPublicNameBuilder(
                name: name,
                kind: ReferenceKind.propertyAccessor,
                numTypeParameters: 0));
          }
        }
      }
      if (member is MethodDeclaration &&
          member.isStatic &&
          !member.isSetter &&
          !member.isOperator) {
        String name = member.name.name;
        if (isPublic(name)) {
          builder.members.add(new UnlinkedPublicNameBuilder(
              name: name,
              kind: member.isGetter
                  ? ReferenceKind.propertyAccessor
                  : ReferenceKind.method,
              numTypeParameters:
                  member.typeParameters?.typeParameters?.length ?? 0));
        }
      }
      if (member is ConstructorDeclaration && member.name != null) {
        String name = member.name.name;
        if (isPublic(name)) {
          builder.members.add(new UnlinkedPublicNameBuilder(
              name: name,
              kind: ReferenceKind.constructor,
              numTypeParameters: 0));
        }
      }
    }
  }
}
