// 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:convert' as convert;

import 'package:analyzer/file_system/file_system.dart';
import 'package:nnbd_migration/src/decorated_type.dart';
import 'package:nnbd_migration/src/nullability_node.dart';
import 'package:nnbd_migration/src/variables.dart';

/// Helper class for reading a postmortem file.
class PostmortemFileReader {
  final NullabilityGraphDeserializer deserializer;

  final NullabilityGraph graph;

  final List<PropagationStep> propagationSteps;

  final Map<String, Map<int, Map<String, NullabilityNode>>> fileDecorations;

  factory PostmortemFileReader.read(File file) {
    var json = convert.json.decode(file.readAsStringSync());
    List<PropagationStep> deserializedSteps = [];
    var deserializer = NullabilityGraphDeserializer(
        json['graph']['nodes'] as List<dynamic>,
        json['graph']['edges'] as List<dynamic>,
        deserializedSteps);
    return PostmortemFileReader._(json, deserializer, deserializedSteps);
  }

  PostmortemFileReader._(dynamic json, this.deserializer, this.propagationSteps)
      : graph = NullabilityGraph.fromJson(json['graph'], deserializer),
        fileDecorations = {
          for (var fileEntry
              in (json['fileDecorations'] as Map<String, dynamic>).entries)
            fileEntry.key: {
              for (var decorationEntry
                  in (fileEntry.value as Map<String, dynamic>).entries)
                int.parse(decorationEntry.key): {
                  for (var roleEntry
                      in (decorationEntry.value as Map<String, dynamic>)
                          .entries)
                    roleEntry.key:
                        deserializer.nodeForId(roleEntry.value as int)
                }
            }
        } {
    _decodePropagationSteps(json['propagationSteps']);
  }

  NodeToIdMapper get idMapper => deserializer;

  void findDecorationsByNode(NullabilityNode node,
      void Function(String path, OffsetEndPair span, String role) callback) {
    for (var fileEntry in fileDecorations.entries) {
      for (var decorationEntry in fileEntry.value.entries) {
        for (var roleEntry in decorationEntry.value.entries) {
          if (identical(roleEntry.value, node)) {
            callback(
                fileEntry.key,
                Variables.spanForUniqueIdentifier(decorationEntry.key),
                roleEntry.key);
          }
        }
      }
    }
  }

  void _decodePropagationSteps(dynamic json) {
    for (var serializedStep in json) {
      var step = PropagationStep.fromJson(serializedStep, deserializer);
      deserializer.recordStepId(step, propagationSteps.length);
      propagationSteps.add(step);
    }
  }
}

/// Helper class for writing to a postmortem file.
class PostmortemFileWriter {
  final File file;

  NullabilityGraph graph;

  final List<PropagationStep> _propagationSteps = [];

  final Map<String, Map<int, Map<String, NullabilityNode>>> _fileDecorations =
      {};

  PostmortemFileWriter(this.file);

  void addPropagationStep(PropagationStep step) {
    _propagationSteps.add(step);
  }

  void clearPropagationSteps() {
    _propagationSteps.clear();
  }

  void storeFileDecorations(
      String path, int location, DecoratedType decoratedType) {
    var roles = <String, NullabilityNode>{};
    decoratedType.recordRoles(roles);
    (_fileDecorations[path] ??= {})[location] = roles;
  }

  void write() {
    var json = <String, Object>{};
    var serializer = NullabilityGraphSerializer();
    json['graph'] = graph.toJson(serializer);
    List<Object> serializedPropagationSteps = [];
    for (var step in _propagationSteps) {
      serializer.recordStepId(step, serializedPropagationSteps.length);
      serializedPropagationSteps.add(step.toJson(serializer));
    }
    json['propagationSteps'] = serializedPropagationSteps;
    json['fileDecorations'] = {
      for (var fileEntry in _fileDecorations.entries)
        fileEntry.key: {
          for (var decorationEntry in (fileEntry.value).entries)
            decorationEntry.key.toString(): {
              for (var roleEntry in (decorationEntry.value).entries)
                roleEntry.key: serializer.idForNode(roleEntry.value)
            }
        }
    };
    file.writeAsStringSync(convert.json.encode(json));
  }
}
