// Copyright (c) 2016, 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:convert';
import 'dart:io';

import 'package:analyzer/src/generated/utilities_dart.dart';
import 'package:analyzer/src/summary/base.dart';
import 'package:analyzer/src/summary/idl.dart';
import 'package:analyzer/src/summary/package_bundle_reader.dart';

/**
 * Collect the inferred types from all the summary files listed in [args] and
 * print them in alphabetical order.
 */
main(List<String> args) {
  SummaryDataStore summaryDataStore = new SummaryDataStore(args);
  InferredTypeCollector collector = new InferredTypeCollector();
  collector.visitSummaryDataStore(summaryDataStore);
  collector.dumpCollectedTypes();
}

/**
 * Visitor class that visits the contents of a summary file and collects the
 * inferred types in it.
 */
class InferredTypeCollector {
  UnlinkedUnit unlinkedUnit;
  LinkedUnit linkedUnit;
  final Map<String, String> inferredTypes = <String, String>{};
  List<String> typeParamsInScope = <String>[];

  /**
   * If an inferred type exists matching the given [slot], record that it is the
   * type of the entity reachable via [path].
   */
  void collectInferredType(int slot, String path) {
    for (EntityRef type in linkedUnit.types) {
      if (type.slot == slot) {
        inferredTypes[path] = formatType(type);
        return;
      }
    }
  }

  /**
   * Collect the inferred type in summary object [obj] (if any), which is
   * reachable via [path].
   *
   * This method may modify [properties] in order to affect how sub-elements
   * are visited.
   */
  void collectInferredTypes(
      SummaryClass obj, Map<String, Object> properties, String path) {
    if (obj is UnlinkedVariable) {
      collectInferredType(obj.inferredTypeSlot, path);
      // As a temporary measure, prevent recursion into the variable's
      // initializer, since AST-based type inference doesn't infer its type
      // correctly yet.  TODO(paulberry): fix.
      properties.remove('initializer');
    } else if (obj is UnlinkedExecutable) {
      collectInferredType(obj.inferredReturnTypeSlot, path);
      // As a temporary measure, prevent recursion into the executable's local
      // variables and local functions, since AST-based type inference doesn't
      // infer locals correctly yet.  TODO(paulberry): fix if necessary.
      properties.remove('localFunctions');
      properties.remove('localVariables');
    } else if (obj is UnlinkedParam) {
      collectInferredType(obj.inferredTypeSlot, path);
      // As a temporary measure, prevent recursion into the parameter's
      // initializer, since AST-based type inference doesn't infer its type
      // correctly yet.  TODO(paulberry): fix.
      properties.remove('initializer');
    }
  }

  /**
   * Print out all the inferred types collected so far, in alphabetical order.
   */
  void dumpCollectedTypes() {
    print('Collected types (${inferredTypes.length}):');
    List<String> paths = inferredTypes.keys.toList();
    paths.sort();
    for (String path in paths) {
      print('$path -> ${inferredTypes[path]}');
    }
  }

  /**
   * Interpret the given [param] as a parameter in a synthetic typedef, and
   * format it as a string.
   */
  String formatParam(UnlinkedParam param) {
    if (param.isFunctionTyped) {
      // TODO(paulberry): fix this case.
      return 'BAD(${JSON.encode(param)})';
    }
    String result;
    if (param.type != null) {
      result = '${formatType(param.type)} ${param.name}';
    } else {
      result = param.name;
    }
    if (param.kind == UnlinkedParamKind.named) {
      result = '{$result}';
    } else if (param.kind == UnlinkedParamKind.positional) {
      result = '[$result]';
    }
    return result;
  }

  /**
   * Convert the reference with index [index] into a string.  If [typeOf] is
   * `true`, the reference is being used in the context of naming a type, so
   * if the entity being referenced is not a type, it will be enclosed in
   * `typeof()` for clarity.
   */
  String formatReference(int index, {bool typeOf: false}) {
    LinkedReference linkedRef = linkedUnit.references[index];
    switch (linkedRef.kind) {
      case ReferenceKind.classOrEnum:
      case ReferenceKind.function:
      case ReferenceKind.propertyAccessor:
      case ReferenceKind.topLevelFunction:
      case ReferenceKind.method:
      case ReferenceKind.typedef:
      case ReferenceKind.prefix:
      case ReferenceKind.topLevelPropertyAccessor:
        break;
      default:
        // TODO(paulberry): fix this case.
        return 'BAD(${JSON.encode(linkedRef.toJson())})';
    }
    int containingReference;
    String name;
    if (index < unlinkedUnit.references.length) {
      containingReference = unlinkedUnit.references[index].prefixReference;
      name = unlinkedUnit.references[index].name;
    } else {
      containingReference = linkedRef.containingReference;
      name = linkedRef.name;
    }
    String result;
    if (containingReference != 0) {
      result = '${formatReference(containingReference)}.$name';
    } else {
      result = name;
    }
    if (linkedRef.kind == ReferenceKind.function) {
      assert(name.isEmpty);
      result += 'localFunction[${linkedRef.localIndex}]';
    }
    if (!typeOf ||
        linkedRef.kind == ReferenceKind.classOrEnum ||
        linkedRef.kind == ReferenceKind.typedef) {
      return result;
    } else {
      return 'typeof($result)';
    }
  }

  /**
   * Interpret the given [entityRef] as a reference to a type, and format it as
   * a string.
   */
  String formatType(EntityRef entityRef) {
    List<int> implicitFunctionTypeIndices =
        entityRef.implicitFunctionTypeIndices;
    if (entityRef.syntheticReturnType != null) {
      String params = entityRef.syntheticParams.map(formatParam).join(', ');
      String retType = formatType(entityRef.syntheticReturnType);
      return '($params) -> $retType';
    }
    if (entityRef.paramReference != 0) {
      return typeParamsInScope[
          typeParamsInScope.length - entityRef.paramReference];
    }
    String result = formatReference(entityRef.reference, typeOf: true);
    List<EntityRef> typeArguments = entityRef.typeArguments.toList();
    while (typeArguments.isNotEmpty && isDynamic(typeArguments.last)) {
      typeArguments.removeLast();
    }
    if (typeArguments.isNotEmpty) {
      result += '<${typeArguments.map(formatType).join(', ')}>';
    }
    if (implicitFunctionTypeIndices.isNotEmpty) {
      result =
          'parameterOf($result, ${implicitFunctionTypeIndices.join(', ')})';
    }
    return result;
  }

  /**
   * Determine if the given [entityRef] represents the pseudo-type `dynamic`.
   */
  bool isDynamic(EntityRef entityRef) {
    if (entityRef.syntheticReturnType != null ||
        entityRef.paramReference != 0) {
      return false;
    }
    return formatReference(entityRef.reference, typeOf: true) == 'dynamic';
  }

  /**
   * Collect all the inferred types contained in [obj], which is reachable via
   * [path].  [properties] is the result of calling `obj.toMap()`, and may be
   * modified before returning.
   */
  void visit(SummaryClass obj, Map<String, Object> properties, String path) {
    List<String> oldTypeParamsInScope = typeParamsInScope;
    Object newTypeParams = properties['typeParameters'];
    if (newTypeParams is List && newTypeParams.isNotEmpty) {
      typeParamsInScope = typeParamsInScope.toList();
      for (Object typeParam in newTypeParams) {
        if (typeParam is UnlinkedTypeParam) {
          typeParamsInScope.add(typeParam.name);
        } else {
          throw new StateError(
              'Unexpected type param type: ${typeParam.runtimeType}');
        }
      }
    }
    collectInferredTypes(obj, properties, path);
    properties.forEach((String key, Object value) {
      if (value is SummaryClass) {
        visit(value, value.toMap(), '$path.$key');
      } else if (value is List) {
        for (int i = 0; i < value.length; i++) {
          Object item = value[i];
          if (item is SummaryClass) {
            Map<String, Object> itemProperties = item.toMap();
            String indexOrName = itemProperties['name'] ?? i.toString();
            visit(item, itemProperties, '$path.$key[$indexOrName]');
          }
        }
      }
    });
    typeParamsInScope = oldTypeParamsInScope;
  }

  /**
   * Collect all the inferred types contained in [summaryDataStore].
   */
  void visitSummaryDataStore(SummaryDataStore summaryDataStore) {
    // Figure out which unlinked units are a part of another library so we won't
    // visit them redundantly.
    Set<String> partOfUris = new Set<String>();
    summaryDataStore.unlinkedMap
        .forEach((String unitUriString, UnlinkedUnit unlinkedUnit) {
      Uri unitUri = Uri.parse(unitUriString);
      for (String relativePartUriString in unlinkedUnit.publicNamespace.parts) {
        partOfUris.add(
            resolveRelativeUri(unitUri, Uri.parse(relativePartUriString))
                .toString());
      }
    });
    summaryDataStore.linkedMap
        .forEach((String libraryUriString, LinkedLibrary linkedLibrary) {
      if (partOfUris.contains(libraryUriString)) {
        return;
      }
      Uri libraryUri = Uri.parse(libraryUriString);
      UnlinkedUnit definingUnlinkedUnit =
          summaryDataStore.unlinkedMap[libraryUriString];
      if (definingUnlinkedUnit != null) {
        visitUnit(
            definingUnlinkedUnit, linkedLibrary.units[0], libraryUriString);
        for (int i = 0;
            i < definingUnlinkedUnit.publicNamespace.parts.length;
            i++) {
          Uri relativePartUri =
              Uri.parse(definingUnlinkedUnit.publicNamespace.parts[i]);
          String unitUriString =
              resolveRelativeUri(libraryUri, relativePartUri).toString();
          UnlinkedUnit unlinkedUnit =
              summaryDataStore.unlinkedMap[unitUriString];
          if (unlinkedUnit != null) {
            visitUnit(
                unlinkedUnit, linkedLibrary.units[i + 1], libraryUriString);
          }
        }
      }
    });
  }

  /**
   * Collect all the inferred types contained in the compilation unit described
   * by [unlinkedUnit] and [linkedUnit], which has URI [libraryUriString].
   */
  void visitUnit(UnlinkedUnit unlinkedUnit, LinkedUnit linkedUnit,
      String libraryUriString) {
    this.unlinkedUnit = unlinkedUnit;
    this.linkedUnit = linkedUnit;
    visit(unlinkedUnit, unlinkedUnit.toMap(), libraryUriString);
    this.unlinkedUnit = null;
    this.linkedUnit = null;
  }
}
