// 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:async_helper/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;
}
