// 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:_fe_analyzer_shared/src/testing/features.dart';
import 'package:expect/async_helper.dart';
import 'package:compiler/src/closure.dart';
import 'package:compiler/src/common.dart';
import 'package:compiler/src/common/codegen.dart';
import 'package:compiler/src/compiler.dart';
import 'package:compiler/src/elements/entities.dart';
import 'package:compiler/src/js/js.dart' as js;
import 'package:compiler/src/js_emitter/model.dart';
import 'package:compiler/src/js_model/element_map.dart';
import 'package:compiler/src/js_model/js_world.dart';
import 'package:kernel/ast.dart' as ir;
import '../equivalence/id_equivalence.dart';
import '../equivalence/id_equivalence_helper.dart';
import '../helpers/program_lookup.dart';

main(List<String> args) {
  asyncTest(() async {
    Directory dataDir = Directory.fromUri(
      Platform.script.resolve('model_data'),
    );
    await checkTests(
      dataDir,
      const ModelDataComputer(),
      args: args,
      testedConfigs: allInternalConfigs,
    );
  });
}

class ModelDataComputer extends DataComputer<Features> {
  const ModelDataComputer();

  /// 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<Features>> actualMap, {
    bool verbose = false,
  }) {
    JClosedWorld closedWorld = compiler.backendClosedWorldForTesting!;
    JsToElementMap elementMap = closedWorld.elementMap;
    MemberDefinition definition = elementMap.getMemberDefinition(member);
    ModelIrComputer(
      compiler.reporter,
      actualMap,
      elementMap,
      member,
      compiler,
      closedWorld.closureDataLookup,
    ).run(definition.node);
  }

  @override
  DataInterpreter<Features> get dataValidator =>
      const FeaturesDataInterpreter(wildcard: '*');
}

class Tags {
  static const String needsCheckedSetter = 'checked';
  static const String getterFlags = 'get';
  static const String setterFlags = 'set';
  static const String parameterCount = 'params';
  static const String call = 'calls';
  static const String parameterStub = 'stubs';
  static const String callStubCall = 'stubCalls';
  static const String callStubAccesses = 'stubAccesses';
  static const String isEmitted = 'emitted';
  static const String isElided = 'elided';
  static const String assignment = 'assign';
  static const String isLazy = 'lazy';
  static const String propertyAccess = 'access';
  static const String switchCase = 'switch';
}

/// AST visitor for computing inference data for a member.
class ModelIrComputer extends IrDataExtractor<Features> {
  final JsToElementMap _elementMap;
  final ClosureData _closureDataLookup;
  final ProgramLookup _programLookup;

  ModelIrComputer(
    DiagnosticReporter reporter,
    Map<Id, ActualData<Features>> actualMap,
    this._elementMap,
    MemberEntity member,
    Compiler compiler,
    this._closureDataLookup,
  ) : _programLookup = ProgramLookup(compiler.backendStrategy),
      super(reporter, actualMap);

  void registerCalls(
    Features features,
    String tag,
    js.Node node, {
    String prefix = '',
    Set<js.PropertyAccess>? handledAccesses,
  }) {
    forEachNode(
      node,
      onCall: (js.Call node) {
        js.Node target = undefer(node.target);
        if (target is js.PropertyAccess) {
          js.Node selector = undefer(target.selector);
          bool fixedNameCall = false;
          String? name;
          if (selector is js.Name) {
            name = selector.key;
          } else if (selector is js.LiteralString) {
            /// Call to fixed backend name, so we include the argument
            /// values to test encoding of optional parameters in native
            /// methods.
            name = selector.value;
            fixedNameCall = true;
          }
          if (name != null) {
            if (fixedNameCall) {
              String arguments = node.arguments.map(js.nodeToString).join(',');
              features.addElement(tag, '${prefix}${name}(${arguments})');
            } else {
              features.addElement(
                tag,
                '${prefix}${name}(${node.arguments.length})',
              );
            }
            handledAccesses?.add(target);
          }
        }
      },
    );
  }

  void registerAccesses(
    Features features,
    String tag,
    js.Node code, {
    String prefix = '',
    Set<js.PropertyAccess>? handledAccesses,
  }) {
    forEachNode(
      code,
      onPropertyAccess: (js.PropertyAccess node) {
        if (handledAccesses?.contains(node) ?? false) {
          return;
        }

        js.Node receiver = undefer(node.receiver);
        String? receiverName;
        if (receiver is js.VariableUse) {
          receiverName = receiver.name;
          if (receiverName == receiverName.toUpperCase() &&
              receiverName != r'$') {
            // Skip holder access.
            receiverName = null;
          }
        } else if (receiver is js.This) {
          receiverName = 'this';
        }

        js.Node selector = undefer(node.selector);
        String? name;
        if (selector is js.Name) {
          name = selector.key;
        } else if (selector is js.LiteralString) {
          /// Call to fixed backend name, so we include the argument
          /// values to test encoding of optional parameters in native
          /// methods.
          name = selector.value;
        }

        if (receiverName != null && name != null) {
          features.addElement(tag, '${prefix}${name}');
        }
      },
    );
  }

  Features? getMemberValue(MemberEntity member) {
    if (member is FieldEntity) {
      Field? field = _programLookup.getField(member);
      if (field != null) {
        Features features = Features();
        if (field.needsCheckedSetter) {
          features.add(Tags.needsCheckedSetter);
        }
        if (field.isElided) {
          features.add(Tags.isElided);
        } else {
          features.add(Tags.isEmitted);
        }
        void registerFlags(String tag, int flags) {
          switch (flags) {
            case 0:
              break;
            case 1:
              features.add(tag, value: 'simple');
              break;
            case 2:
              features.add(tag, value: 'intercepted');
              break;
            case 3:
              features.add(tag, value: 'interceptedThis');
              break;
          }
        }

        registerFlags(Tags.getterFlags, field.getterFlags);
        registerFlags(Tags.setterFlags, field.setterFlags);

        Class cls = _programLookup.getClass(member.enclosingClass!)!;
        for (StubMethod stub in cls.callStubs) {
          if (stub.element == member) {
            registerCalls(
              features,
              Tags.callStubCall,
              stub.code,
              prefix: '${stub.name!.key}:',
            );
            registerAccesses(
              features,
              Tags.callStubAccesses,
              stub.code,
              prefix: '${stub.name!.key}:',
            );
          }
        }

        return features;
      }
      StaticField? staticField = _programLookup.getStaticField(member);
      if (staticField != null) {
        Features features = Features();
        features.add(Tags.isEmitted);
        if (staticField.isLazy) {
          features.add(Tags.isLazy);
        }
        return features;
      }
    } else if (member is FunctionEntity) {
      Method? method = _programLookup.getMethod(member);
      if (method != null) {
        Features features = Features();
        js.Expression code = method.code;
        if (code is js.Fun) {
          features[Tags.parameterCount] = '${code.params.length}';
        }

        Set<js.PropertyAccess> handledAccesses = Set();

        registerCalls(
          features,
          Tags.call,
          code,
          handledAccesses: handledAccesses,
        );
        if (method is DartMethod) {
          for (ParameterStubMethod stub in method.parameterStubs) {
            registerCalls(
              features,
              Tags.parameterStub,
              stub.code,
              prefix: '${stub.name!.key}:',
              handledAccesses: handledAccesses,
            );
          }
        }

        forEachNode(
          code,
          onAssignment: (js.Assignment node) {
            final leftHandSide = undefer(node.leftHandSide);
            if (leftHandSide is js.PropertyAccess) {
              js.Node selector = undefer(leftHandSide.selector);
              String? name;
              if (selector is js.Name) {
                name = selector.key;
              } else if (selector is js.LiteralString) {
                name = selector.value;
              }
              if (name != null) {
                features.addElement(Tags.assignment, '${name}');
                handledAccesses.add(leftHandSide);
              }
            }
          },
        );

        registerAccesses(
          features,
          Tags.propertyAccess,
          code,
          handledAccesses: handledAccesses,
        );

        forEachNode(
          code,
          onSwitch: (js.Switch node) {
            features.add(Tags.switchCase);
          },
        );

        return features;
      }
    }
    return null;
  }

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

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

js.Node undefer(js.Node node) {
  if (node is js.DeferredExpression) return undefer(node.value);
  if (node is ModularName) return undefer(node.value);
  return node;
}
