// Copyright (c) 2019, 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/closure.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/entities.dart';
import 'package:compiler/src/js_backend/backend.dart';
import 'package:compiler/src/js_model/element_map.dart';
import 'package:compiler/src/js_model/js_world.dart';
import 'package:compiler/src/ssa/logging.dart';
import 'package:compiler/src/ssa/ssa.dart';
import 'package:compiler/src/util/features.dart';
import 'package:kernel/ast.dart' as ir;
import '../equivalence/id_equivalence.dart';
import '../equivalence/id_equivalence_helper.dart';

main(List<String> args) {
  asyncTest(() async {
    Directory dataDir = new Directory.fromUri(Platform.script.resolve('data'));
    bool strict = args.contains('-s');
    await checkTests(dataDir, new OptimizationDataComputer(strict: strict),
        options: [Flags.disableInlining], args: args);
  });
}

class OptimizationDataValidator
    implements DataInterpreter<OptimizationTestLog> {
  final bool strict;

  const OptimizationDataValidator({this.strict: false});

  @override
  String getText(OptimizationTestLog actualData) {
    Features features = new Features();
    for (OptimizationLogEntry entry in actualData.entries) {
      features.addElement(
          entry.tag, entry.features.getText().replaceAll(',', '&'));
    }
    return features.getText();
  }

  @override
  bool isEmpty(OptimizationTestLog actualData) {
    return actualData == null || actualData.entries.isEmpty;
  }

  @override
  String isAsExpected(OptimizationTestLog actualLog, String expectedLog) {
    expectedLog ??= '';
    if (expectedLog == '') {
      return actualLog.entries.isEmpty
          ? null
          : "Expected empty optimization log.";
    }
    if (expectedLog == '*') {
      return null;
    }
    List<OptimizationLogEntry> actualDataEntries = actualLog.entries.toList();
    Features expectedLogEntries = Features.fromText(expectedLog);
    List<String> errorsFound = <String>[];
    expectedLogEntries.forEach((String tag, dynamic expectedEntryData) {
      List<OptimizationLogEntry> actualDataForTag =
          actualDataEntries.where((data) => data.tag == tag).toList();
      for (OptimizationLogEntry entry in actualDataForTag) {
        actualDataEntries.remove(entry);
      }
      if (expectedEntryData == '') {
        errorsFound.add("Unknown expected entry '$tag'");
      } else if (expectedEntryData is List && expectedEntryData.isEmpty) {
        if (actualDataForTag.isNotEmpty) {
          errorsFound.add('Non-empty log found for tag $tag');
        }
      } else if (expectedEntryData == '*') {
        // Anything allowed.
      } else if (expectedEntryData is List) {
        for (Object object in expectedEntryData) {
          String expectedLogEntryText = '$object';
          bool expectMatch = true;
          if (expectedLogEntryText.startsWith('!')) {
            expectedLogEntryText = expectedLogEntryText.substring(1);
            expectMatch = false;
          }
          expectedLogEntryText = expectedLogEntryText.replaceAll('&', ',');
          Features expectedLogEntry = Features.fromText(expectedLogEntryText);
          bool matchFound = false;
          for (OptimizationLogEntry actualLogEntry in actualDataForTag) {
            bool validData = true;
            expectedLogEntry.forEach((String key, Object expectedValue) {
              Object actualValue = actualLogEntry.features[key];
              if ('$actualValue' != '$expectedValue') {
                validData = false;
              }
            });
            if (validData) {
              actualDataForTag.remove(actualLogEntry);
              matchFound = true;
              break;
            }
          }
          if (expectMatch) {
            if (!matchFound) {
              errorsFound.add("No match found for $tag=[$object]");
            }
          } else {
            if (matchFound) {
              errorsFound.add("Unexpected match found for $tag=[$object]");
            }
          }
        }
      } else {
        errorsFound.add("Unknown expected entry $tag=$expectedEntryData");
      }
    });
    if (strict) {
      for (OptimizationLogEntry entry in actualDataEntries) {
        errorsFound.add("Extra entry ${entry.tag}=${entry.features.getText()}");
      }
    }
    return errorsFound.isNotEmpty ? errorsFound.join(', ') : null;
  }
}

class OptimizationDataComputer extends DataComputer<OptimizationTestLog> {
  final bool strict;

  const OptimizationDataComputer({this.strict: false});

  /// Compute type inference data for [member] from kernel based inference.
  ///
  /// Fills [actualMap] with the data.
  @override
  void computeMemberData(Compiler compiler, MemberEntity member,
      Map<Id, ActualData<OptimizationTestLog>> actualMap,
      {bool verbose: false}) {
    JsClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
    JsToElementMap elementMap = closedWorld.elementMap;
    MemberDefinition definition = elementMap.getMemberDefinition(member);
    new OptimizationIrComputer(compiler.reporter, actualMap, elementMap, member,
            compiler.backend, closedWorld.closureDataLookup)
        .run(definition.node);
  }

  @override
  DataInterpreter<OptimizationTestLog> get dataValidator =>
      new OptimizationDataValidator(strict: strict);
}

/// AST visitor for computing inference data for a member.
class OptimizationIrComputer extends IrDataExtractor<OptimizationTestLog> {
  final JavaScriptBackend backend;
  final JsToElementMap _elementMap;
  final ClosureData _closureDataLookup;

  OptimizationIrComputer(
      DiagnosticReporter reporter,
      Map<Id, ActualData<OptimizationTestLog>> actualMap,
      this._elementMap,
      MemberEntity member,
      this.backend,
      this._closureDataLookup)
      : super(reporter, actualMap);

  OptimizationTestLog getLog(MemberEntity member) {
    SsaFunctionCompiler functionCompiler = backend.functionCompiler;
    return functionCompiler.optimizer.loggersForTesting[member];
  }

  OptimizationTestLog getMemberValue(MemberEntity member) {
    if (member is FunctionEntity) {
      return getLog(member);
    }
    return null;
  }

  @override
  OptimizationTestLog computeMemberValue(Id id, ir.Member node) {
    return getMemberValue(_elementMap.getMember(node));
  }

  @override
  OptimizationTestLog computeNodeValue(Id id, ir.TreeNode node) {
    if (node is ir.FunctionExpression || node is ir.FunctionDeclaration) {
      ClosureRepresentationInfo info = _closureDataLookup.getClosureInfo(node);
      return getMemberValue(info.callMethod);
    }
    return null;
  }
}
