// Copyright (c) 2015, 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:async';
import 'dart:convert';
import 'dart:io';

import 'package:analysis_server/protocol/protocol.dart';
import 'package:analysis_server/protocol/protocol_constants.dart';
import 'package:analysis_server/protocol/protocol_generated.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:logging/logging.dart';
import 'package:path/path.dart' as path;

import 'instrumentation_input_converter.dart';
import 'log_file_input_converter.dart';
import 'operation.dart';

/// Common input converter superclass for sharing implementation.
abstract class CommonInputConverter extends Converter<String, Operation?> {
  static final ERROR_PREFIX = 'Server responded with an error: ';
  final Logger logger = Logger('InstrumentationInputConverter');
  final Set<String> eventsSeen = <String>{};

  /// A mapping from request/response id to request json
  /// for those requests for which a response has not been processed.
  final Map<String, Object?> requestMap = {};

  /// A mapping from request/response id to a completer
  /// for those requests for which a response has not been processed.
  /// The completer is called with the actual json response
  /// when it becomes available.
  final Map<String, Completer> responseCompleters = {};

  /// A mapping from request/response id to the actual response result
  /// for those responses that have not been processed.
  final Map<String, Object?> responseMap = {};

  /// A mapping of current overlay content
  /// parallel to what is in the analysis server
  /// so that we can update the file system.
  final Map<String, String> overlays = {};

  /// The prefix used to determine if a request parameter is a file path.
  final String rootPrefix = path.rootPrefix(path.current);

  /// A mapping of source path prefixes
  /// from location where instrumentation or log file was generated
  /// to the target location of the source using during performance measurement.
  final PathMap srcPathMap;

  /// The root directory for all source being modified
  /// during performance measurement.
  final String tmpSrcDirPath;

  CommonInputConverter(this.tmpSrcDirPath, this.srcPathMap);

  Map<String, Object?> asMap(dynamic value) => value as Map<String, Object?>;

  Map<String, Object?>? asMap2(dynamic value) => value as Map<String, Object?>?;

  /// Return an operation for the notification or `null` if none.
  Operation? convertNotification(Map<String, dynamic> json) {
    String event = json['event'];
    if (event == SERVER_NOTIFICATION_STATUS) {
      // {"event":"server.status","params":{"analysis":{"isAnalyzing":false}}}
      var params = asMap2(json['params']);
      if (params != null) {
        var analysis = asMap2(params['analysis']);
        if (analysis != null && analysis['isAnalyzing'] == false) {
          return WaitForAnalysisCompleteOperation();
        }
      }
    }
    if (event == SERVER_NOTIFICATION_CONNECTED) {
      // {"event":"server.connected","params":{"version":"1.7.0"}}
      return StartServerOperation();
    }
    if (eventsSeen.add(event)) {
      logger.log(Level.INFO, 'Ignored notification: $event\n  $json');
    }
    return null;
  }

  /// Return an operation for the request or `null` if none.
  Operation convertRequest(Map<String, Object?> origJson) {
    var json = asMap(translateSrcPaths(origJson));
    requestMap[json['id'] as String] = json;
    var method = json['method'] as String;
    // Sanity check operations that modify source
    // to ensure that the operation is on source in temp space
    if (method == ANALYSIS_REQUEST_UPDATE_CONTENT) {
      // Track overlays in parallel with the analysis server
      // so that when an overlay is removed, the file can be updated on disk
      var request = Request.fromJson(json)!;
      var params = AnalysisUpdateContentParams.fromRequest(request);
      params.files.forEach((String filePath, change) {
        if (change is AddContentOverlay) {
          var content = change.content;
          overlays[filePath] = content;
        } else if (change is ChangeContentOverlay) {
          var content = overlays[filePath];
          if (content == null) {
            throw 'expected cached overlay content\n$json';
          }
          overlays[filePath] = SourceEdit.applySequence(content, change.edits);
        } else if (change is RemoveContentOverlay) {
          var content = overlays.remove(filePath);
          if (content == null) {
            throw 'expected cached overlay content\n$json';
          }
          if (!path.isWithin(tmpSrcDirPath, filePath)) {
            throw 'found path referencing source outside temp space\n$filePath\n$json';
          }
          File(filePath).writeAsStringSync(content);
        } else {
          throw 'unknown overlay change $change\n$json';
        }
      });
      return RequestOperation(this, json);
    }
    // Track performance for completion notifications
    if (method == COMPLETION_REQUEST_GET_SUGGESTIONS) {
      return CompletionRequestOperation(this, json);
    }
    // TODO(danrubel) replace this with code
    // that just forwards the translated request
    if (method == ANALYSIS_REQUEST_GET_HOVER ||
        method == ANALYSIS_REQUEST_SET_ANALYSIS_ROOTS ||
        method == ANALYSIS_REQUEST_SET_PRIORITY_FILES ||
        method == ANALYSIS_REQUEST_SET_SUBSCRIPTIONS ||
        method == ANALYSIS_REQUEST_UPDATE_OPTIONS ||
        method == EDIT_REQUEST_GET_ASSISTS ||
        method == EDIT_REQUEST_GET_AVAILABLE_REFACTORINGS ||
        method == EDIT_REQUEST_GET_FIXES ||
        method == EDIT_REQUEST_GET_REFACTORING ||
        method == EDIT_REQUEST_SORT_MEMBERS ||
        method == EXECUTION_REQUEST_CREATE_CONTEXT ||
        method == EXECUTION_REQUEST_DELETE_CONTEXT ||
        method == EXECUTION_REQUEST_MAP_URI ||
        method == EXECUTION_REQUEST_SET_SUBSCRIPTIONS ||
        method == SEARCH_REQUEST_FIND_ELEMENT_REFERENCES ||
        method == SEARCH_REQUEST_FIND_MEMBER_DECLARATIONS ||
        method == SERVER_REQUEST_GET_VERSION ||
        method == SERVER_REQUEST_SET_SUBSCRIPTIONS) {
      return RequestOperation(this, json);
    }
    throw 'unknown request: $method\n  $json';
  }

  /// Return an operation for the recorded/expected response.
  Operation convertResponse(Map<String, dynamic> json) {
    return ResponseOperation(this, asMap(requestMap.remove(json['id'])),
        asMap(translateSrcPaths(json)));
  }

  void logOverlayContent() {
    logger.log(Level.WARNING, '${overlays.length} overlays');
    var allPaths = overlays.keys.toList()..sort();
    for (var filePath in allPaths) {
      logger.log(Level.WARNING, 'overlay $filePath\n${overlays[filePath]}');
    }
  }

  /// Process an error response from the server by either
  /// completing the associated completer in the [responseCompleters]
  /// or stashing it in [responseMap] if no completer exists.
  void processErrorResponse(String id, exception) {
    var result = exception;
    if (exception is UnimplementedError) {
      var message = exception.message;
      if (message!.startsWith(ERROR_PREFIX)) {
        result = json.decode(message.substring(ERROR_PREFIX.length));
      }
    }
    processResponseResult(id, result);
  }

  /// Process the expected response by completing the given completer
  /// with the result if it has already been received,
  /// or caching the completer to be completed when the server
  /// returns the associated result.
  /// Return a future that completes when the response is received
  /// or `null` if the response has already been received
  /// and the completer completed.
  Future<void>? processExpectedResponse(String id, Completer completer) {
    if (responseMap.containsKey(id)) {
      logger.log(Level.INFO, 'processing cached response $id');
      completer.complete(responseMap.remove(id));
      return null;
    } else {
      logger.log(Level.INFO, 'waiting for response $id');
      responseCompleters[id] = completer;
      return completer.future;
    }
  }

  /// Process a success response result from the server by either
  /// completing the associated completer in the [responseCompleters]
  /// or stashing it in [responseMap] if no completer exists.
  /// The response result may be `null`.
  void processResponseResult(String id, result) {
    var completer = responseCompleters[id];
    if (completer != null) {
      logger.log(Level.INFO, 'processing response $id');
      completer.complete(result);
    } else {
      logger.log(Level.INFO, 'caching response $id');
      responseMap[id] = result;
    }
  }

  /// Recursively translate source paths in the specified JSON to reference
  /// the temporary source used during performance measurement rather than
  /// the original source when the instrumentation or log file was generated.
  dynamic translateSrcPaths(json) {
    if (json is String) {
      return srcPathMap.translate(json);
    }
    if (json is List) {
      var result = [];
      for (var i = 0; i < json.length; ++i) {
        result.add(translateSrcPaths(json[i]));
      }
      return result;
    }
    if (json is Map) {
      var result = <String, Object?>{};
      json.forEach((origKey, value) {
        result[translateSrcPaths(origKey)] = translateSrcPaths(value);
      });
      return result;
    }
    return json;
  }
}

/// [InputConverter] converts an input stream
/// into a series of operations to be sent to the analysis server.
/// The input stream can be either an instrumentation or log file.
class InputConverter extends Converter<String, Operation?> {
  final Logger logger = Logger('InputConverter');

  /// A mapping of source path prefixes
  /// from location where instrumentation or log file was generated
  /// to the target location of the source using during performance measurement.
  final PathMap srcPathMap;

  /// The root directory for all source being modified
  /// during performance measurement.
  final String tmpSrcDirPath;

  /// The number of lines read before the underlying converter was determined
  /// or the end of file was reached.
  int _headerLineCount = 0;

  /// The underlying converter used to translate lines into operations
  /// or `null` if it has not yet been determined.
  Converter<String, Operation?>? _converter;

  /// [_active] is `true` if converting lines to operations
  /// or `false` if an exception has occurred.
  bool _active = true;

  InputConverter(this.tmpSrcDirPath, this.srcPathMap);

  @override
  Operation? convert(String line) {
    if (!_active) {
      return null;
    }
    try {
      var converter = _getConverter(line);
      if (converter == null) {
        logger.log(Level.INFO, 'skipped input line: $line');
        return null;
      }
      return converter.convert(line);
    } catch (_) {
      _active = false;
      rethrow;
    }
  }

  @override
  _InputSink startChunkedConversion(outSink) {
    return _InputSink(this, outSink);
  }

  /// Return the previously determined converter, or determine it from the
  /// given [line]. Return `null` if cannot be determined yet. Throw an
  /// exception if could not be determined after some number of tries.
  Converter<String, Operation?>? _getConverter(String line) {
    var converter = _converter;
    if (converter != null) {
      return converter;
    }

    if (_headerLineCount++ == 20) {
      throw 'Failed to determine input file format';
    }

    if (InstrumentationInputConverter.isFormat(line)) {
      _converter = InstrumentationInputConverter(tmpSrcDirPath, srcPathMap);
    } else if (LogFileInputConverter.isFormat(line)) {
      _converter = LogFileInputConverter(tmpSrcDirPath, srcPathMap);
    }

    return _converter;
  }
}

/// A container of [PathMapEntry]s used to translate a source path in the log
/// before it is sent to the analysis server.
class PathMap {
  final List<PathMapEntry> entries = [];

  void add(String oldSrcPrefix, String newSrcPrefix) {
    entries.add(PathMapEntry(oldSrcPrefix, newSrcPrefix));
  }

  String translate(String original) {
    var result = original;
    for (var entry in entries) {
      result = entry.translate(result);
    }
    return result;
  }
}

/// An entry in [PathMap] used to translate a source path in the log
/// before it is sent to the analysis server.
class PathMapEntry {
  final String oldSrcPrefix;
  final String newSrcPrefix;

  PathMapEntry(this.oldSrcPrefix, this.newSrcPrefix);

  String translate(String original) {
    return original.startsWith(oldSrcPrefix)
        ? '$newSrcPrefix${original.substring(oldSrcPrefix.length)}'
        : original;
  }
}

class _InputSink extends ChunkedConversionSink<String> {
  final Converter<String, Operation?> converter;
  final Sink<Operation?> outSink;

  _InputSink(this.converter, this.outSink);

  @override
  void add(String line) {
    var op = converter.convert(line);
    if (op != null) {
      outSink.add(op);
    }
  }

  @override
  void close() {
    outSink.close();
  }
}
