// Copyright (c) 2014, 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:analyzer_plugin/protocol/protocol_common.dart';

/**
 * An outcome of a condition checking operation.
 */
class RefactoringStatus {
  /**
   * The current severity of this [RefactoringStatus] - the maximum of the
   * severities of its [entries].
   */
  RefactoringProblemSeverity _severity = null;

  /**
   * A list of [RefactoringProblem]s.
   */
  final List<RefactoringProblem> problems = [];

  /**
   * Creates a new OK [RefactoringStatus].
   */
  RefactoringStatus();

  /**
   * Creates a new [RefactoringStatus] with the ERROR severity.
   */
  factory RefactoringStatus.error(String msg, [Location location]) {
    RefactoringStatus status = new RefactoringStatus();
    status.addError(msg, location);
    return status;
  }

  /**
   * Creates a new [RefactoringStatus] with the FATAL severity.
   */
  factory RefactoringStatus.fatal(String msg, [Location location]) {
    RefactoringStatus status = new RefactoringStatus();
    status.addFatalError(msg, location);
    return status;
  }

  /**
   * Creates a new [RefactoringStatus] with the WARNING severity.
   */
  factory RefactoringStatus.warning(String msg, [Location location]) {
    RefactoringStatus status = new RefactoringStatus();
    status.addWarning(msg, location);
    return status;
  }

  /**
   * Returns `true` if the severity is FATAL or ERROR.
   */
  bool get hasError {
    return _severity == RefactoringProblemSeverity.FATAL ||
        _severity == RefactoringProblemSeverity.ERROR;
  }

  /**
   * Returns `true` if the severity is FATAL.
   */
  bool get hasFatalError => _severity == RefactoringProblemSeverity.FATAL;

  /**
   * Returns `true` if the severity is WARNING.
   */
  bool get hasWarning => _severity == RefactoringProblemSeverity.WARNING;

  /**
   * Return `true` if the severity is `OK`.
   */
  bool get isOK => _severity == null;

  /**
   * Returns the message of the [RefactoringProblem] with highest severity;
   * may be `null` if no problems.
   */
  String get message {
    RefactoringProblem problem = this.problem;
    if (problem == null) {
      return null;
    }
    return problem.message;
  }

  /**
   * Returns the first [RefactoringProblem] with the highest severity.
   *
   * Returns `null` if no entries.
   */
  RefactoringProblem get problem {
    for (RefactoringProblem problem in problems) {
      if (problem.severity == _severity) {
        return problem;
      }
    }
    return null;
  }

  /**
   * Returns the current severity of this [RefactoringStatus].
   */
  RefactoringProblemSeverity get severity => _severity;

  /**
   * Adds an ERROR problem with the given message and location.
   */
  void addError(String msg, [Location location]) {
    _addProblem(new RefactoringProblem(RefactoringProblemSeverity.ERROR, msg,
        location: location));
  }

  /**
   * Adds a FATAL problem with the given message and location.
   */
  void addFatalError(String msg, [Location location]) {
    _addProblem(new RefactoringProblem(RefactoringProblemSeverity.FATAL, msg,
        location: location));
  }

  /**
   * Merges [other] into this [RefactoringStatus].
   *
   * The [other]'s entries are added to this.
   *
   * The resulting severity is the more severe of this and [other] severities.
   *
   * Merging with `null` is allowed - it has no effect.
   */
  void addStatus(RefactoringStatus other) {
    if (other == null) {
      return;
    }
    problems.addAll(other.problems);
    _severity = RefactoringProblemSeverity.max(_severity, other.severity);
  }

  /**
   * Adds a WARNING problem with the given message and location.
   */
  void addWarning(String msg, [Location location]) {
    _addProblem(new RefactoringProblem(RefactoringProblemSeverity.WARNING, msg,
        location: location));
  }

  @override
  String toString() {
    StringBuffer sb = new StringBuffer();
    sb.write("<");
    if (_severity == null) {
      sb.write('OK');
    } else {
      sb.write(_severity.name);
    }
    if (!isOK) {
      sb.write("\n");
      for (RefactoringProblem problem in problems) {
        sb.write("\t");
        sb.write(problem);
        sb.write("\n");
      }
    }
    sb.write(">");
    return sb.toString();
  }

  /**
   * Adds the given [RefactoringProblem] and updates [severity].
   */
  void _addProblem(RefactoringProblem problem) {
    problems.add(problem);
    // update maximum severity
    RefactoringProblemSeverity severity = problem.severity;
    _severity = RefactoringProblemSeverity.max(_severity, severity);
  }
}
