// Copyright (c) 2017, 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 'package:compiler/src/commandline_options.dart';
import 'package:compiler/src/common.dart';
import 'package:compiler/src/common_elements.dart';
import 'package:compiler/src/compiler.dart';
import 'package:compiler/src/elements/elements.dart';
import 'package:compiler/src/elements/entities.dart';
import 'package:compiler/src/resolution/tree_elements.dart';
import 'package:compiler/src/tree/nodes.dart' as ast;
import 'package:expect/expect.dart';
import 'package:kernel/ast.dart' as ir;

import '../annotated_code_helper.dart';
import '../memory_compiler.dart';
import '../equivalence/id_equivalence.dart';
import '../kernel/compiler_helper.dart';

/// Function that compiles [code] with [options] and returns the [Compiler] object.
typedef Future<Compiler> CompileFunction(
    AnnotatedCode code, Uri mainUri, List<String> options);

/// Function that computes a data mapping for [member].
///
/// Fills [actualMap] with the data and [sourceSpanMap] with the source spans
/// for the data origin.
typedef void ComputeMemberDataFunction(Compiler compiler, MemberEntity member,
    Map<Id, String> actualMap, Map<Id, SourceSpan> sourceSpanMap,
    {bool verbose});

/// Compile [code] from .dart sources.
Future<Compiler> compileFromSource(
    AnnotatedCode code, Uri mainUri, List<String> options) async {
  Compiler compiler = compilerFor(
      memorySourceFiles: {'main.dart': code.sourceCode}, options: options);
  compiler.stopAfterTypeInference = true;
  await compiler.run(mainUri);
  return compiler;
}

/// Compile [code] from .dill sources.
Future<Compiler> compileFromDill(
    AnnotatedCode code, Uri mainUri, List<String> options) async {
  Compiler compiler = await compileWithDill(
      entryPoint: mainUri,
      memorySourceFiles: {'main.dart': code.sourceCode},
      options: [Flags.disableTypeInference]..addAll(options),
      beforeRun: (Compiler compiler) {
        compiler.stopAfterTypeInference = true;
      });
  return compiler;
}

/// Compute expected and actual data for all members defined in [annotatedCode].
///
/// Actual data is computed using [computeMemberData] and [code] is compiled
/// using [compileFunction].
Future<IdData> computeData(
    String annotatedCode,
    ComputeMemberDataFunction computeMemberData,
    CompileFunction compileFunction,
    {List<String> options: const <String>[],
    bool verbose: false}) async {
  AnnotatedCode code =
      new AnnotatedCode.fromText(annotatedCode, commentStart, commentEnd);
  Map<Id, String> expectedMap = computeExpectedMap(code);
  Map<Id, String> actualMap = <Id, String>{};
  Map<Id, SourceSpan> sourceSpanMap = <Id, SourceSpan>{};
  Uri mainUri = Uri.parse('memory:main.dart');
  Compiler compiler = await compileFunction(code, mainUri, options);
  ElementEnvironment elementEnvironment =
      compiler.backendClosedWorldForTesting.elementEnvironment;
  LibraryEntity mainLibrary = elementEnvironment.mainLibrary;
  elementEnvironment.forEachClass(mainLibrary, (ClassEntity cls) {
    elementEnvironment.forEachClassMember(cls,
        (ClassEntity declarer, MemberEntity member) {
      if (cls == declarer) {
        computeMemberData(compiler, member, actualMap, sourceSpanMap,
            verbose: verbose);
      }
    });
  });
  elementEnvironment.forEachLibraryMember(mainLibrary, (MemberEntity member) {
    computeMemberData(compiler, member, actualMap, sourceSpanMap,
        verbose: verbose);
  });
  return new IdData(compiler, elementEnvironment, mainUri, expectedMap,
      actualMap, sourceSpanMap);
}

/// Data collected by [computeData].
class IdData {
  final Compiler compiler;
  final ElementEnvironment elementEnvironment;
  final Uri mainUri;
  final Map<Id, String> expectedMap;
  final Map<Id, String> actualMap;
  final Map<Id, SourceSpan> sourceSpanMap;

  IdData(this.compiler, this.elementEnvironment, this.mainUri, this.expectedMap,
      this.actualMap, this.sourceSpanMap);
}

/// Compiles the [annotatedCode] with the provided [options] and calls
/// [computeMemberData] for each member. The result is checked against the
/// expected data derived from [annotatedCode].
Future checkCode(
    String annotatedCode,
    ComputeMemberDataFunction computeMemberData,
    CompileFunction compileFunction,
    {List<String> options: const <String>[],
    bool verbose: false}) async {
  IdData data = await computeData(
      annotatedCode, computeMemberData, compileFunction,
      options: options, verbose: verbose);

  data.actualMap.forEach((Id id, String actual) {
    if (!data.expectedMap.containsKey(id)) {
      if (actual != '') {
        reportHere(data.compiler.reporter, data.sourceSpanMap[id],
            'Id $id not expected in ${data.expectedMap.keys}');
      }
      Expect.equals('', actual);
    } else {
      String expected = data.expectedMap.remove(id);
      if (actual != expected) {
        reportHere(data.compiler.reporter, data.sourceSpanMap[id],
            'expected:${expected},actual:${actual}');
      }
      Expect.equals(expected, actual);
    }
  });

  data.expectedMap.forEach((Id id, String expected) {
    reportHere(
        data.compiler.reporter,
        computeSpannable(data.elementEnvironment, data.mainUri, id),
        'expected:${expected},actual:null');
  });
  Expect.isTrue(
      data.expectedMap.isEmpty, "Ids not found: ${data.expectedMap}.");
}

/// Compute a [Spannable] from an [id] in the library [mainUri].
Spannable computeSpannable(
    ElementEnvironment elementEnvironment, Uri mainUri, Id id) {
  if (id is NodeId) {
    return new SourceSpan(mainUri, id.value, id.value + 1);
  } else if (id is ElementId) {
    LibraryEntity library = elementEnvironment.lookupLibrary(mainUri);
    if (id.className != null) {
      ClassEntity cls =
          elementEnvironment.lookupClass(library, id.className, required: true);
      return elementEnvironment.lookupClassMember(cls, id.memberName);
    } else {
      return elementEnvironment.lookupLibraryMember(library, id.memberName);
    }
  }
  throw new UnsupportedError('Unsupported id $id.');
}

/// Compute the expectancy map from [code].
Map<Id, String> computeExpectedMap(AnnotatedCode code) {
  Map<Id, String> map = <Id, String>{};
  for (Annotation annotation in code.annotations) {
    String text = annotation.text;
    int colonPos = text.indexOf(':');
    Id id;
    String expected;
    if (colonPos == -1) {
      id = new NodeId(annotation.offset);
      expected = text;
    } else {
      id = new ElementId(text.substring(0, colonPos));
      expected = text.substring(colonPos + 1);
    }
    map[id] = expected;
  }
  return map;
}

/// Mixin used for computing [Id] data.
abstract class ComputerMixin {
  Map<Id, String> get actualMap;
  Map<Id, SourceSpan> get sourceSpanMap;

  void registerValue(SourceSpan sourceSpan, Id id, String value) {
    if (id != null && value != null) {
      sourceSpanMap[id] = sourceSpan;
      actualMap[id] = value;
    }
  }
}

/// Abstract AST visitor for computing [Id] data.
abstract class AbstractResolvedAstComputer extends ast.Visitor
    with AstEnumeratorMixin, ComputerMixin {
  final DiagnosticReporter reporter;
  final Map<Id, String> actualMap;
  final Map<Id, SourceSpan> sourceSpanMap;
  final ResolvedAst resolvedAst;

  AbstractResolvedAstComputer(
      this.reporter, this.actualMap, this.sourceSpanMap, this.resolvedAst);

  TreeElements get elements => resolvedAst.elements;

  void computeForElement(AstElement element) {
    ElementId id = computeElementId(element);
    if (id == null) return;
    String value = computeElementValue(element);
    registerValue(element.sourcePosition, id, value);
  }

  void computeForNode(ast.Node node, AstElement element) {
    NodeId id = computeNodeId(node, element);
    if (id == null) return;
    String value = computeNodeValue(node, element);
    SourceSpan sourceSpan = new SourceSpan(resolvedAst.sourceUri,
        node.getBeginToken().charOffset, node.getEndToken().charEnd);
    registerValue(sourceSpan, id, value);
  }

  String computeElementValue(AstElement element);

  String computeNodeValue(ast.Node node, AstElement element);

  void run() {
    resolvedAst.node.accept(this);
  }

  visitNode(ast.Node node) {
    node.visitChildren(this);
  }

  visitVariableDefinitions(ast.VariableDefinitions node) {
    for (ast.Node child in node.definitions) {
      AstElement element = elements[child];
      if (element == null) {
        reportHere(reporter, child, 'No element for variable.');
      } else if (!element.isLocal) {
        computeForElement(element);
      } else {
        computeForNode(child, element);
      }
    }
    visitNode(node);
  }

  visitFunctionExpression(ast.FunctionExpression node) {
    AstElement element = elements.getFunctionDefinition(node);
    if (!element.isLocal) {
      computeForElement(element);
    } else {
      computeForNode(node, element);
    }
    visitNode(node);
  }

  visitSend(ast.Send node) {
    computeForNode(node, null);
    visitNode(node);
  }

  visitSendSet(ast.SendSet node) {
    computeForNode(node, null);
    visitNode(node);
  }
}

/// Abstract IR visitor for computing [Id] data.
abstract class AbstractIrComputer extends ir.Visitor
    with IrEnumeratorMixin, ComputerMixin {
  final Map<Id, String> actualMap;
  final Map<Id, SourceSpan> sourceSpanMap;

  AbstractIrComputer(this.actualMap, this.sourceSpanMap);

  void computeForMember(ir.Member member) {
    ElementId id = computeElementId(member);
    if (id == null) return;
    String value = computeMemberValue(member);
    registerValue(computeSpannable(member), id, value);
  }

  void computeForNode(ir.TreeNode node) {
    NodeId id = computeNodeId(node);
    if (id == null) return;
    String value = computeNodeValue(node);
    registerValue(computeSpannable(node), id, value);
  }

  Spannable computeSpannable(ir.TreeNode node) {
    return new SourceSpan(
        Uri.parse(node.location.file), node.fileOffset, node.fileOffset + 1);
  }

  String computeMemberValue(ir.Member member);

  String computeNodeValue(ir.TreeNode node);

  void run(ir.Node root) {
    root.accept(this);
  }

  defaultNode(ir.Node node) {
    node.visitChildren(this);
  }

  defaultMember(ir.Member node) {
    computeForMember(node);
    super.defaultMember(node);
  }

  visitMethodInvocation(ir.MethodInvocation node) {
    computeForNode(node);
    super.visitMethodInvocation(node);
  }

  visitPropertyGet(ir.PropertyGet node) {
    computeForNode(node);
    super.visitPropertyGet(node);
  }

  visitVariableDeclaration(ir.VariableDeclaration node) {
    computeForNode(node);
    super.visitVariableDeclaration(node);
  }

  visitFunctionDeclaration(ir.FunctionDeclaration node) {
    computeForNode(node);
    super.visitFunctionDeclaration(node);
  }

  visitFunctionExpression(ir.FunctionExpression node) {
    computeForNode(node);
    super.visitFunctionExpression(node);
  }
}
