// 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.

library input.transformer;

import 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:analysis_server/src/constants.dart';
import 'package:analysis_server/src/protocol.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 = new Logger('InstrumentationInputConverter');
  final Set<String> eventsSeen = new Set<String>();

  /**
   * A mapping from request/response id to request json
   * for those requests for which a response has not been processed.
   */
  final Map<String, dynamic> 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, dynamic> 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 Map<String, String> srcPathMap;

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

  /**
   * The diagnostic port for Analysis Server or `null` if none.
   */
  final int diagnosticPort;

  CommonInputConverter(this.tmpSrcDirPath, this.srcPathMap,
      {this.diagnosticPort});

  /**
   * Return an operation for the notification or `null` if none.
   */
  Operation convertNotification(Map<String, dynamic> json) {
    String event = json['event'];
    if (event == SERVER_STATUS) {
      // {"event":"server.status","params":{"analysis":{"isAnalyzing":false}}}
      Map<String, dynamic> params = json['params'];
      if (params != null) {
        Map<String, dynamic> analysis = params['analysis'];
        if (analysis != null && analysis['isAnalyzing'] == false) {
          return new WaitForAnalysisCompleteOperation();
        }
      }
    }
    if (event == SERVER_CONNECTED) {
      // {"event":"server.connected","params":{"version":"1.7.0"}}
      return new StartServerOperation(diagnosticPort: diagnosticPort);
    }
    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, dynamic> origJson) {
    Map<String, dynamic> json = translateSrcPaths(origJson);
    requestMap[json['id']] = json;
    String method = json['method'];
    // Sanity check operations that modify source
    // to ensure that the operation is on source in temp space
    if (method == ANALYSIS_UPDATE_CONTENT) {
      // Track overlays in parallel with the analysis server
      // so that when an overlay is removed, the file can be updated on disk
      Request request = new Request.fromJson(json);
      var params = new AnalysisUpdateContentParams.fromRequest(request);
      params.files.forEach((String filePath, change) {
        if (change is AddContentOverlay) {
          String content = change.content;
          if (content == null) {
            throw 'expected new overlay content\n$json';
          }
          overlays[filePath] = content;
        } else if (change is ChangeContentOverlay) {
          String 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) {
          String 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';
          }
          new File(filePath).writeAsStringSync(content);
        } else {
          throw 'unknown overlay change $change\n$json';
        }
      });
      return new RequestOperation(this, json);
    }
    // Track performance for completion notifications
    if (method == COMPLETION_GET_SUGGESTIONS) {
      return new CompletionRequestOperation(this, json);
    }
    // TODO(danrubel) replace this with code
    // that just forwards the translated request
    if (method == ANALYSIS_GET_HOVER ||
        method == ANALYSIS_SET_ANALYSIS_ROOTS ||
        method == ANALYSIS_SET_PRIORITY_FILES ||
        method == ANALYSIS_SET_SUBSCRIPTIONS ||
        method == ANALYSIS_UPDATE_OPTIONS ||
        method == EDIT_GET_ASSISTS ||
        method == EDIT_GET_AVAILABLE_REFACTORINGS ||
        method == EDIT_GET_FIXES ||
        method == EDIT_GET_REFACTORING ||
        method == EDIT_SORT_MEMBERS ||
        method == EXECUTION_CREATE_CONTEXT ||
        method == EXECUTION_DELETE_CONTEXT ||
        method == EXECUTION_MAP_URI ||
        method == EXECUTION_SET_SUBSCRIPTIONS ||
        method == SEARCH_FIND_ELEMENT_REFERENCES ||
        method == SEARCH_FIND_MEMBER_DECLARATIONS ||
        method == SERVER_GET_VERSION ||
        method == SERVER_SET_SUBSCRIPTIONS) {
      return new RequestOperation(this, json);
    }
    throw 'unknown request: $method\n  $json';
  }

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

  /**
   * 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) {
      if (exception.message.startsWith(ERROR_PREFIX)) {
        result = JSON.decode(exception.message.substring(ERROR_PREFIX.length));
      }
    }
    processResponseResult(id, result);
  }

  /**
   * Process the expected response by completing the given completer
   * with the result if it has alredy 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 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) {
    Completer 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.
   */
  translateSrcPaths(json) {
    if (json is String) {
      String result = json;
      srcPathMap.forEach((String oldPrefix, String newPrefix) {
        if (json.startsWith(oldPrefix)) {
          result = '$newPrefix${json.substring(oldPrefix.length)}';
        }
      });
      return result;
    }
    if (json is List) {
      List result = [];
      for (int i = 0; i < json.length; ++i) {
        result.add(translateSrcPaths(json[i]));
      }
      return result;
    }
    if (json is Map) {
      Map<String, dynamic> result = new Map<String, dynamic>();
      json.forEach((String 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 instrumenation or log file.
 */
class InputConverter extends Converter<String, Operation> {
  final Logger logger = new 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 Map<String, String> srcPathMap;

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

  /**
   * The diagnostic port for Analysis Server or `null` if none.
   */
  final int diagnosticPort;

  /**
   * 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, {this.diagnosticPort});

  @override
  Operation convert(String line) {
    if (!active) {
      return null;
    }
    if (converter != null) {
      try {
        return converter.convert(line);
      } catch (e) {
        active = false;
        rethrow;
      }
    }
    if (headerLineCount == 20) {
      throw 'Failed to determine input file format';
    }
    if (InstrumentationInputConverter.isFormat(line)) {
      converter = new InstrumentationInputConverter(tmpSrcDirPath, srcPathMap,
          diagnosticPort: diagnosticPort);
    } else if (LogFileInputConverter.isFormat(line)) {
      converter = new LogFileInputConverter(tmpSrcDirPath, srcPathMap,
          diagnosticPort: diagnosticPort);
    }
    if (converter != null) {
      return converter.convert(line);
    }
    logger.log(Level.INFO, 'skipped input line: $line');
    return null;
  }

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

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

  _InputSink(this.converter, this.outSink);

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

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