// 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:io';
import 'package:async_helper/async_helper.dart';
import 'package:compiler/src/commandline_options.dart';
import 'package:compiler/src/common.dart';
import 'package:compiler/src/compiler.dart';
import 'package:compiler/src/diagnostics/diagnostic_listener.dart';
import 'package:compiler/src/elements/elements.dart';
import 'package:compiler/src/elements/entities.dart';
import 'package:compiler/src/kernel/element_map.dart';
import 'package:compiler/src/kernel/kernel_backend_strategy.dart';
import 'package:compiler/src/resolution/access_semantics.dart';
import 'package:compiler/src/resolution/send_structure.dart';
import 'package:compiler/src/tree/nodes.dart' as ast;
import 'package:kernel/ast.dart' as ir;
import 'package:sourcemap_testing/src/annotated_code_helper.dart';
import '../equivalence/id_equivalence.dart';
import '../equivalence/id_equivalence_helper.dart';

const List<String> dataDirectories = const <String>[
  '../closure/data',
  '../inference/data',
  '../jumps/data',
];

main(List<String> args) {
  asyncTest(() async {
    for (String path in dataDirectories) {
      Directory dataDir = new Directory.fromUri(Platform.script.resolve(path));
      await for (FileSystemEntity entity in dataDir.list()) {
        if (args.isNotEmpty && !args.contains(entity.uri.pathSegments.last)) {
          continue;
        }
        print('Checking ${entity.uri}');
        String annotatedCode =
            await new File.fromUri(entity.uri).readAsString();
        AnnotatedCode code =
            new AnnotatedCode.fromText(annotatedCode, commentStart, commentEnd);
        // Pretend this is a dart2js_native test to allow use of 'native'
        // keyword and import of private libraries.
        Uri entryPoint =
            Uri.parse('memory:sdk/tests/compiler/dart2js_native/main.dart');
        Map<String, String> memorySourceFiles = {
          entryPoint.path: code.sourceCode
        };
        await compareData(entryPoint, memorySourceFiles, computeAstMemberData,
            computeIrMemberData,
            options: [Flags.disableTypeInference, stopAfterTypeInference]);
      }
    }
  });
}

/// Compute a descriptive mapping of the [Id]s in [_member] as a
/// [MemberElement].
///
/// Fills [actualMap] with the data and [sourceSpanMap] with the source spans
/// for the data origin.
void computeAstMemberData(
    Compiler compiler, MemberEntity _member, Map<Id, ActualData> actualMap,
    {bool verbose: false}) {
  MemberElement member = _member;
  ResolvedAst resolvedAst = member.resolvedAst;
  new ResolvedAstComputer(compiler.reporter, actualMap, resolvedAst).run();
}

/// Mixin used for computing a descriptive mapping of the [Id]s in a member.
class ComputerMixin {
  String computeMemberName(String className, String memberName) {
    if (className != null) {
      return 'member:$className.$memberName';
    }
    return 'member:$memberName';
  }

  String computeLocalName(String localName) {
    return 'local:$localName';
  }

  String computeGetName(String propertyName) {
    return 'get:$propertyName';
  }

  String computeInvokeName(String propertyName) {
    return 'invoke:$propertyName';
  }

  String computeSetName(String propertyName) {
    return 'set:$propertyName';
  }

  String get loopName => 'loop';

  String get gotoName => 'goto';

  String get switchName => 'switch';

  String get switchCaseName => 'case';

  String get labelName => 'label';
}

/// AST visitor for computing a descriptive mapping of the [Id]s in a member.
class ResolvedAstComputer extends AstDataExtractor with ComputerMixin {
  ResolvedAstComputer(DiagnosticReporter reporter,
      Map<Id, ActualData> actualMap, ResolvedAst resolvedAst)
      : super(reporter, actualMap, resolvedAst);

  @override
  String computeNodeValue(Id id, ast.Node node, AstElement element) {
    if (element != null && element.isLocal) {
      return computeLocalName(element.name);
    }
    if (node is ast.Loop) {
      return loopName;
    } else if (node is ast.GotoStatement) {
      return gotoName;
    } else if (node is ast.SwitchStatement) {
      return switchName;
    } else if (node is ast.SwitchCase) {
      return switchCaseName;
    } else if (node is ast.LabeledStatement) {
      return labelName;
    }

    dynamic sendStructure;
    if (node is ast.Send) {
      sendStructure = elements.getSendStructure(node);
      if (sendStructure == null) return null;

      String getDynamicName() {
        switch (sendStructure.semantics.kind) {
          case AccessKind.PARAMETER:
          case AccessKind.FINAL_PARAMETER:
          case AccessKind.LOCAL_VARIABLE:
          case AccessKind.FINAL_LOCAL_VARIABLE:
          case AccessKind.LOCAL_FUNCTION:
            return sendStructure.semantics.element.name;
          case AccessKind.THIS_PROPERTY:
          case AccessKind.DYNAMIC_PROPERTY:
          case AccessKind.CONDITIONAL_DYNAMIC_PROPERTY:
            DynamicAccess access = sendStructure.semantics;
            return access.name.text;
          default:
            return null;
        }
      }

      switch (sendStructure.kind) {
        case SendStructureKind.GET:
          String dynamicName = getDynamicName();
          if (dynamicName != null) return computeGetName(dynamicName);
          break;
        case SendStructureKind.BINARY:
        case SendStructureKind.UNARY:
          return computeInvokeName(sendStructure.operator.selectorName);
        case SendStructureKind.INDEX:
          return computeGetName('[]');
        case SendStructureKind.INDEX_SET:
          return computeSetName('[]=');
        case SendStructureKind.COMPOUND_INDEX_SET:
        case SendStructureKind.INDEX_PREFIX:
        case SendStructureKind.INDEX_POSTFIX:
          if (id.kind == IdKind.update) {
            return computeSetName('[]=');
          } else if (id.kind == IdKind.invoke) {
            return computeInvokeName(
                sendStructure.operator.binaryOperator.name);
          } else {
            return computeGetName('[]');
          }
          break;
        case SendStructureKind.EQUALS:
          return computeInvokeName('==');
        case SendStructureKind.NOT_EQUALS:
          return computeInvokeName('==');
        case SendStructureKind.INVOKE:
        case SendStructureKind.INCOMPATIBLE_INVOKE:
          switch (sendStructure.semantics.kind) {
            case AccessKind.LOCAL_VARIABLE:
            case AccessKind.FINAL_LOCAL_VARIABLE:
            case AccessKind.PARAMETER:
            case AccessKind.FINAL_PARAMETER:
            case AccessKind.EXPRESSION:
              if (id.kind == IdKind.invoke) {
                return computeInvokeName('call');
              } else if (id.kind == IdKind.node) {
                String dynamicName = getDynamicName();
                if (dynamicName != null) return computeGetName(dynamicName);
              }
              break;
            case AccessKind.STATIC_FIELD:
            case AccessKind.FINAL_STATIC_FIELD:
            case AccessKind.TOPLEVEL_FIELD:
            case AccessKind.FINAL_TOPLEVEL_FIELD:
            case AccessKind.STATIC_GETTER:
            case AccessKind.TOPLEVEL_GETTER:
            case AccessKind.SUPER_FIELD:
            case AccessKind.SUPER_FINAL_FIELD:
            case AccessKind.SUPER_GETTER:
              if (id.kind == IdKind.invoke) {
                return computeInvokeName('call');
              }
              break;
            default:
              String dynamicName = getDynamicName();
              if (dynamicName != null) return computeInvokeName(dynamicName);
          }
          break;
        case SendStructureKind.SET:
          String dynamicName = getDynamicName();
          if (dynamicName != null) return computeSetName(dynamicName);
          break;
        case SendStructureKind.PREFIX:
        case SendStructureKind.POSTFIX:
        case SendStructureKind.COMPOUND:
          if (id.kind == IdKind.invoke) {
            return computeInvokeName(
                sendStructure.operator.binaryOperator.name);
          } else {
            String dynamicName = getDynamicName();
            if (dynamicName != null) {
              if (id.kind == IdKind.update) {
                return computeSetName(dynamicName);
              } else {
                return computeGetName(dynamicName);
              }
            }
          }
          break;
        default:
      }
    }
    if (sendStructure != null) {
      return '<unknown:$node (${node.runtimeType}) $sendStructure>';
    }
    return '<unknown:$node (${node.runtimeType})>';
  }

  @override
  String computeElementValue(Id id, AstElement element) {
    return computeMemberName(element.enclosingClass?.name, element.name);
  }
}

/// Compute a descriptive mapping of the [Id]s in [member] as a kernel based
/// member.
///
/// Fills [actualMap] with the data and [sourceSpanMap] with the source spans
/// for the data origin.
void computeIrMemberData(
    Compiler compiler, MemberEntity member, Map<Id, ActualData> actualMap,
    {bool verbose: false}) {
  KernelBackendStrategy backendStrategy = compiler.backendStrategy;
  KernelToElementMapForBuilding elementMap = backendStrategy.elementMap;
  MemberDefinition definition = elementMap.getMemberDefinition(member);
  assert(
      definition.kind == MemberKind.regular ||
          definition.kind == MemberKind.constructor,
      failedAt(member, "Unexpected member definition $definition"));
  new IrComputer(compiler.reporter, actualMap).run(definition.node);
}

/// IR visitor for computing a descriptive mapping of the [Id]s in a member.
class IrComputer extends IrDataExtractor with ComputerMixin {
  IrComputer(DiagnosticReporter reporter, Map<Id, ActualData> actualMap)
      : super(reporter, actualMap);

  @override
  String computeNodeValue(Id id, ir.TreeNode node) {
    if (node is ir.VariableDeclaration) {
      return computeLocalName(node.name);
    } else if (node is ir.FunctionDeclaration) {
      return computeLocalName(node.variable.name);
    } else if (node is ir.FunctionExpression) {
      return computeLocalName('');
    } else if (node is ir.MethodInvocation) {
      ir.TreeNode receiver = node.receiver;
      if (receiver is ir.VariableGet &&
          receiver.variable.parent is ir.FunctionDeclaration) {
        // This is an invocation of a named local function.
        return computeInvokeName(receiver.variable.name);
      } else if (node.name.name == '[]') {
        return computeGetName('[]');
      } else if (node.name.name == '[]=') {
        return computeSetName('[]=');
      } else {
        return computeInvokeName(node.name.name);
      }
    } else if (node is ir.PropertyGet) {
      return computeGetName(node.name.name);
    } else if (node is ir.PropertySet) {
      return computeSetName(node.name.name);
    } else if (node is ir.VariableGet) {
      return computeGetName(node.variable.name);
    } else if (node is ir.VariableSet) {
      return computeSetName(node.variable.name);
    } else if (node is ir.DoStatement) {
      return loopName;
    } else if (node is ir.ForStatement) {
      return loopName;
    } else if (node is ir.ForInStatement) {
      return loopName;
    } else if (node is ir.WhileStatement) {
      return loopName;
    } else if (node is ir.BreakStatement) {
      return gotoName;
    } else if (node is ir.ContinueSwitchStatement) {
      return gotoName;
    } else if (node is ir.SwitchStatement) {
      return switchName;
    } else if (node is ir.SwitchCase) {
      return switchCaseName;
    } else if (node is ir.LabeledStatement) {
      return labelName;
    } else if (node is ir.LoadLibrary) {
      return computeInvokeName('call');
    }
    return '<unknown:$node (${node.runtimeType})>';
  }

  @override
  String computeMemberValue(Id id, ir.Member member) {
    return computeMemberName(member.enclosingClass?.name, member.name.name);
  }
}
