// 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 'package:kernel/ast.dart' as ir;
import 'package:kernel/class_hierarchy.dart' as ir;
import 'package:kernel/type_environment.dart' as ir;

import 'package:front_end/src/api_unstable/dart2js.dart' as ir
    show LocatedMessage;

import '../diagnostics/diagnostic_listener.dart';
import '../diagnostics/messages.dart';
import '../diagnostics/source_span.dart';
import '../kernel/element_map_impl.dart';
import '../environment.dart';
import '../ir/static_type.dart';
import '../js_backend/annotations.dart';
import '../options.dart';
import '../serialization/serialization.dart';
import '../util/enumset.dart';
import 'annotations.dart';
import 'constants.dart';
import 'impact.dart';
import 'scope.dart';

class ModularCore {
  final ir.Component component;
  final Dart2jsConstantEvaluator constantEvaluator;

  ModularCore(this.component, this.constantEvaluator);
}

class ModularMemberData {
  final ScopeModel scopeModel;
  final ImpactBuilderData impactBuilderData;

  ModularMemberData(this.scopeModel, this.impactBuilderData);
}

abstract class ModularStrategy {
  List<PragmaAnnotationData> getPragmaAnnotationData(ir.Member node);

  // TODO(johnniwinther): Avoid the need for passing [pragmaAnnotations].
  ModularMemberData getModularMemberData(
      ir.Member node, EnumSet<PragmaAnnotation> pragmaAnnotations);
}

/// Data computed for an entire compilation module.
class ModuleData {
  static const String tag = 'ModuleData';

  // TODO(joshualitt) Support serializing ModularMemberData;
  final Map<ir.Member, ImpactBuilderData> impactData;

  ModuleData(this.impactData);

  factory ModuleData.fromDataSource(DataSource source) {
    source.begin(tag);
    var impactData = source
        .readMemberNodeMap(() => ImpactBuilderData.fromDataSource(source));
    source.end(tag);
    return ModuleData(impactData);
  }

  void toDataSink(DataSink sink) {
    sink.begin(tag);
    sink.writeMemberNodeMap<ImpactBuilderData>(
        impactData, (e) => e.toDataSink(sink));
    sink.end(tag);
  }
}

/// Compute [ModularMemberData] from the IR.
ModularMemberData computeModularMemberData(ir.Member node,
    {CompilerOptions options,
    ir.TypeEnvironment typeEnvironment,
    ir.ClassHierarchy classHierarchy,
    ScopeModel scopeModel,
    EnumSet<PragmaAnnotation> annotations}) {
  var staticTypeCache = StaticTypeCacheImpl();
  var impactBuilderData = ImpactBuilder(
          ir.StaticTypeContext(node, typeEnvironment, cache: staticTypeCache),
          staticTypeCache,
          classHierarchy,
          scopeModel.variableScopeModel,
          useAsserts: options.enableUserAssertions,
          inferEffectivelyFinalVariableTypes:
              !annotations.contains(PragmaAnnotation.disableFinal))
      .computeImpact(node);
  return ModularMemberData(scopeModel, impactBuilderData);
}

ModuleData computeModuleData(
    ir.Component component,
    Set<Uri> includedLibraries,
    CompilerOptions options,
    DiagnosticReporter reporter,
    Environment environment,
    KernelToElementMapImpl elementMap) {
  var classHierarchy = elementMap.classHierarchy;
  var typeEnvironment = elementMap.typeEnvironment;
  var constantEvaluator = elementMap.constantEvaluator;
  var result = <ir.Member, ImpactBuilderData>{};
  void computeForMember(ir.Member member) {
    var scopeModel = ScopeModel.from(member, constantEvaluator);
    var annotations = processMemberAnnotations(
        options, reporter, member, computePragmaAnnotationDataFromIr(member));
    result[member] = computeModularMemberData(member,
            options: options,
            typeEnvironment: typeEnvironment,
            classHierarchy: classHierarchy,
            scopeModel: scopeModel,
            annotations: annotations)
        .impactBuilderData;
  }

  for (var library in component.libraries) {
    if (!includedLibraries.contains(library.importUri)) continue;
    library.members.forEach(computeForMember);
    for (var cls in library.classes) {
      cls.members.forEach(computeForMember);
    }
  }
  return ModuleData(result);
}

void reportLocatedMessage(DiagnosticReporter reporter,
    ir.LocatedMessage message, List<ir.LocatedMessage> context) {
  DiagnosticMessage diagnosticMessage =
      _createDiagnosticMessage(reporter, message);
  var infos = <DiagnosticMessage>[];
  for (ir.LocatedMessage message in context) {
    infos.add(_createDiagnosticMessage(reporter, message));
  }
  reporter.reportError(diagnosticMessage, infos);
}

DiagnosticMessage _createDiagnosticMessage(
    DiagnosticReporter reporter, ir.LocatedMessage message) {
  var sourceSpan = SourceSpan(
      message.uri, message.charOffset, message.charOffset + message.length);
  return reporter.createMessage(
      sourceSpan, MessageKind.GENERIC, {'text': message.message});
}
