// Copyright (c) 2016, 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 analyzer.src.task.yaml;

import 'package:analyzer/src/context/cache.dart';
import 'package:analyzer/src/dart/scanner/scanner.dart';
import 'package:analyzer/src/generated/engine.dart' hide AnalysisTask;
import 'package:analyzer/src/generated/error.dart';
import 'package:analyzer/src/generated/java_engine.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/task/general.dart';
import 'package:analyzer/task/general.dart';
import 'package:analyzer/task/model.dart';
import 'package:analyzer/task/yaml.dart';
import 'package:source_span/source_span.dart';
import 'package:yaml/yaml.dart';

/**
 * A task that scans the content of a YAML file, producing a YAML document.
 */
class ParseYamlTask extends SourceBasedAnalysisTask {
  /**
   * The name of the input whose value is the content of the file.
   */
  static const String CONTENT_INPUT_NAME = 'CONTENT_INPUT_NAME';

  /**
   * The task descriptor describing this kind of task.
   */
  static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
      'ParseYamlTask',
      createTask,
      buildInputs,
      <ResultDescriptor>[YAML_DOCUMENT, YAML_ERRORS, LINE_INFO],
      suitabilityFor: suitabilityFor);

  /**
   * Initialize a newly created task to access the content of the source
   * associated with the given [target] in the given [context].
   */
  ParseYamlTask(InternalAnalysisContext context, AnalysisTarget target)
      : super(context, target);

  @override
  TaskDescriptor get descriptor => DESCRIPTOR;

  @override
  void internalPerform() {
    Source source = target.source;
    String uri = source.uri.toString();
    String content = getRequiredInput(CONTENT_INPUT_NAME);

    if (context.getModificationStamp(source) < 0) {
      String message = 'Content could not be read';
      if (context is InternalAnalysisContext) {
        CacheEntry entry =
            (context as InternalAnalysisContext).getCacheEntry(target);
        CaughtException exception = entry.exception;
        if (exception != null) {
          message = exception.toString();
        }
      }
      //
      // Record outputs.
      //
      outputs[YAML_DOCUMENT] = loadYamlDocument('', sourceUrl: uri);
      outputs[YAML_ERRORS] = <AnalysisError>[
        new AnalysisError(
            source, 0, 0, ScannerErrorCode.UNABLE_GET_CONTENT, [message])
      ];
      outputs[LINE_INFO] = new LineInfo(<int>[0]);
    } else {
      YamlDocument document;
      List<AnalysisError> errors = <AnalysisError>[];
      try {
        document = loadYamlDocument(content, sourceUrl: uri);
      } on YamlException catch (exception) {
        SourceSpan span = exception.span;
        int offset = span.start.offset;
        int length = span.end.offset - offset;
        errors.add(new AnalysisError(source, offset, length,
            YamlErrorCode.PARSE_ERROR, [exception.message]));
      } catch (exception, stackTrace) {
        throw new AnalysisException('Error while parsing ${source.fullName}',
            new CaughtException(exception, stackTrace));
      }
      //
      // Record outputs.
      //
      outputs[YAML_DOCUMENT] = document;
      outputs[YAML_ERRORS] = errors;
      outputs[LINE_INFO] = new LineInfo.fromContent(content);
    }
  }

  /**
   * Return a map from the names of the inputs of this kind of task to the task
   * input descriptors describing those inputs for a task with the given
   * [source].
   */
  static Map<String, TaskInput> buildInputs(Source source) {
    return <String, TaskInput>{CONTENT_INPUT_NAME: CONTENT.of(source)};
  }

  /**
   * Create a [ParseYamlTask] based on the given [target] in the given [context].
   */
  static ParseYamlTask createTask(
      AnalysisContext context, AnalysisTarget target) {
    return new ParseYamlTask(context, target);
  }

  /**
   * Return an indication of how suitable this task is for the given [target].
   */
  static TaskSuitability suitabilityFor(AnalysisTarget target) {
    if (target is Source && target.shortName.endsWith('.yaml')) {
      return TaskSuitability.HIGHEST;
    }
    return TaskSuitability.NONE;
  }
}

/**
 * The error codes used for errors in YAML files.
 */
class YamlErrorCode extends ErrorCode {
  // TODO(brianwilkerson) Move this class to error.dart.

  /**
   * An error code indicating that there is a syntactic error in the file.
   *
   * Parameters:
   * 0: the error message from the parse error
   */
  static const YamlErrorCode PARSE_ERROR =
      const YamlErrorCode('PARSE_ERROR', '{0}');

  /**
   * Initialize a newly created error code to have the given [name]. The message
   * associated with the error will be created from the given [message]
   * template. The correction associated with the error will be created from the
   * given [correction] template.
   */
  const YamlErrorCode(String name, String message, [String correction])
      : super(name, message, correction);

  @override
  ErrorSeverity get errorSeverity => ErrorSeverity.ERROR;

  @override
  ErrorType get type => ErrorType.COMPILE_TIME_ERROR;
}
