// Copyright (c) 2012, 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:_internal' as internal;
import 'dart:convert' show JSON;

patch class Error {
  /* patch */ static String _objectToString(Object object) {
    return Object._toString(object);
  }

  /* patch */ static String _stringToSafeString(String string) {
    return JSON.encode(string);
  }

  /* patch */ StackTrace get stackTrace => _stackTrace;

  StackTrace _stackTrace;
}

class _AssertionError extends Error implements AssertionError {
  _AssertionError._create(
      this._failedAssertion, this._url, this._line, this._column);

  static _throwNew(int assertionStart, int assertionEnd)
      native "AssertionError_throwNew";

  static void _checkAssertion(condition, int start, int end) {
    if (condition is Function) {
      condition = condition();
    }
    if (!condition) {
      _throwNew(start, end);
    }
  }

  String toString() {
    if (_url == null) {
      return _failedAssertion;
    }
    var columnInfo = "";
    if (_column > 0) {
      // Only add column information if it is valid.
      columnInfo = " pos $_column";
    }
    return "'$_url': Failed assertion: line $_line$columnInfo: "
        "'$_failedAssertion' is not true.";
  }
  final String _failedAssertion;
  final String _url;
  final int _line;
  final int _column;
}

class _TypeError extends _AssertionError implements TypeError {
  _TypeError._create(String url, int line, int column, this._errorMsg)
      : super._create("is assignable", url, line, column);

  static _throwNew(int location,
                   Object src_value,
                   _Type dst_type,
                   String dst_name,
                   String bound_error_msg)
      native "TypeError_throwNew";

  static _throwNewIfNotLoaded(_LibraryPrefix prefix,
                              int location,
                              Object src_value,
                              _Type dst_type,
                              String dst_name,
                              String bound_error_msg) {
    if (!prefix.isLoaded()) {
      _throwNew(location, src_value, dst_type, dst_name, bound_error_msg);
    }
  }

  String toString() => _errorMsg;

  final String _errorMsg;
}

class _CastError extends Error implements CastError {
  _CastError._create(this._url, this._line, this._column, this._errorMsg);

  // A CastError is allocated by TypeError._throwNew() when dst_name equals
  // Symbols::InTypeCast().

  String toString() => _errorMsg;

  // Fields _url, _line, and _column are only used for debugging purposes.
  final String _url;
  final int _line;
  final int _column;
  final String _errorMsg;
}

patch class FallThroughError {
  FallThroughError._create(this._url, this._line);

  static _throwNew(int case_clause_pos) native "FallThroughError_throwNew";

  /* patch */ String toString() {
    return "'$_url': Switch case fall-through at line $_line.";
  }

  // These new fields cannot be declared final, because a constructor exists
  // in the original version of this patched class.
  String _url;
  int _line;
}

class _InternalError {
  const _InternalError(this._msg);
  String toString() => "InternalError: '${_msg}'";
  final String _msg;
}

patch class UnsupportedError {
  static _throwNew(String msg) {
    throw new UnsupportedError(msg);
  }
}

patch class CyclicInitializationError {
  static _throwNew(String variableName) {
    throw new CyclicInitializationError(variableName);
  }
}

patch class AbstractClassInstantiationError {
  AbstractClassInstantiationError._create(
      this._className, this._url, this._line);

  static _throwNew(int case_clause_pos, String className)
      native "AbstractClassInstantiationError_throwNew";

  /* patch */ String toString() {
    return "Cannot instantiate abstract class $_className: "
           "_url '$_url' line $_line";
  }

  // These new fields cannot be declared final, because a constructor exists
  // in the original version of this patched class.
  String _url;
  int _line;
}

patch class NoSuchMethodError {
  // The compiler emits a call to _throwNew when it cannot resolve a static
  // method at compile time. The receiver is actually the literal class of the
  // unresolved method.
  static void _throwNew(Object receiver,
                        String memberName,
                        int invocation_type,
                        List arguments,
                        List argumentNames,
                        List existingArgumentNames) {
    int numNamedArguments = argumentNames == null ? 0 : argumentNames.length;
    int numPositionalArguments = arguments == null ? 0 : arguments.length;
    numPositionalArguments -= numNamedArguments;
    List positionalArguments;
    if (numPositionalArguments == 0) {
      // Differ between no arguments specified and 0 arguments.
      // TODO(srdjan): This can currently occur for unresolvable static methods.
      // In that case, the arguments are evaluated but not passed to the
      // throwing stub (see EffectGraphVisitor::BuildThrowNoSuchMethodError and
      // Parser::ThrowNoSuchMethodError)).
      positionalArguments = argumentNames == null ? null : [];
    } else {
      positionalArguments = arguments.sublist(0, numPositionalArguments);
    }
    Map<Symbol, dynamic> namedArguments = new Map<Symbol, dynamic>();
    for (int i = 0; i < numNamedArguments; i++) {
      var arg_value = arguments[numPositionalArguments + i];
      namedArguments[new Symbol(argumentNames[i])] = arg_value;
    }
    throw new NoSuchMethodError._withType(receiver,
                                          new Symbol(memberName),
                                          invocation_type,
                                          positionalArguments,
                                          namedArguments,
                                          existingArgumentNames);
  }

  static void _throwNewIfNotLoaded(_LibraryPrefix prefix,
                                   Object receiver,
                                   String memberName,
                                   int invocation_type,
                                   List arguments,
                                   List argumentNames,
                                   List existingArgumentNames) {
    if (!prefix.isLoaded()) {
      _throwNew(receiver, memberName, invocation_type, arguments,
                argumentNames, existingArgumentNames);
    }
  }

  // Remember the type from the invocation mirror or static compilation
  // analysis when thrown directly with _throwNew. A negative value means
  // that no information is available.
  final int _invocation_type;

  NoSuchMethodError(Object this._receiver,
                    Symbol this._memberName,
                    List this._arguments,
                    Map<Symbol, dynamic> this._namedArguments,
                    [List existingArgumentNames = null])
      : this._existingArgumentNames = existingArgumentNames,
        this._invocation_type = -1;

  // This constructor seems to be called with either strings or
  // values read from another NoSuchMethodError.
  NoSuchMethodError._withType(Object this._receiver,
                              /*String|Symbol*/ memberName,
                              this._invocation_type,
                              List this._arguments,
                              Map<dynamic, dynamic> namedArguments,
                              [List existingArgumentNames = null])
      : this._memberName =
            (memberName is String) ? new Symbol(memberName) : memberName,
        this._namedArguments =
            (namedArguments == null)
                ? null
                : new Map<Symbol, dynamic>.fromIterable(
                    namedArguments.keys,
                    key: (k) => (k is String) ? new Symbol(k) : k,
                    value: (k) => namedArguments[k]),
        this._existingArgumentNames = existingArgumentNames;


  String _developerMessage(args_mismatch) {
    if (_invocation_type < 0) {
      return "";
    }
    var type = _invocation_type & _InvocationMirror._TYPE_MASK;
    var level = (_invocation_type >> _InvocationMirror._CALL_SHIFT) &
         _InvocationMirror._CALL_MASK;
    var type_str =
        (const ["method", "getter", "setter", "getter or setter", "variable"])[type];
    var args_message = args_mismatch ? " with matching arguments" : "";
    var msg;
    var memberName =
        (_memberName == null) ? "" : internal.Symbol.getUnmangledName(_memberName);

    if (type == _InvocationMirror._LOCAL_VAR) {
      return "cannot assign to final variable '$memberName'.\n\n";
    }
    switch (level) {
      case _InvocationMirror._DYNAMIC: {
        if (_receiver == null) {
          msg = "The null object does not have a $type_str '$memberName'"
              "$args_message.";
        } else {
          if (_receiver is Function) {
            msg = "Closure call with mismatched arguments: "
                "function '$memberName'";
          } else {
            msg = "Class '${_receiver.runtimeType}' has no instance $type_str "
                "'$memberName'$args_message.";
          }
        }
        break;
      }
      case _InvocationMirror._SUPER: {
        msg = "Super class of class '${_receiver.runtimeType}' has no instance "
              "$type_str '$memberName'$args_message.";
        break;
      }
      case _InvocationMirror._STATIC: {
        msg = "No static $type_str '$memberName' declared in class "
            "'$_receiver'.";
        break;
      }
      case _InvocationMirror._CONSTRUCTOR: {
        msg = "No constructor '$memberName'$args_message declared in class '$_receiver'.";
        break;
      }
      case _InvocationMirror._TOP_LEVEL: {
        msg = "No top-level $type_str '$memberName'$args_message declared.";
        break;
      }
    }
    return "$msg\n\n";
  }

  /* patch */ String toString() {
    StringBuffer actual_buf = new StringBuffer();
    int i = 0;
    if (_arguments == null) {
      // Actual arguments unknown.
      // TODO(srdjan): Remove once arguments are passed for unresolvable
      // static methods.
      actual_buf.write("...");
    } else {
      for (; i < _arguments.length; i++) {
        if (i > 0) {
          actual_buf.write(", ");
        }
        actual_buf.write(Error.safeToString(_arguments[i]));
      }
    }
    if (_namedArguments != null) {
      _namedArguments.forEach((Symbol key, var value) {
        if (i > 0) {
          actual_buf.write(", ");
        }
        actual_buf.write(internal.Symbol.getUnmangledName(key));
        actual_buf.write(": ");
        actual_buf.write(Error.safeToString(value));
        i++;
      });
    }
    var args_mismatch = _existingArgumentNames != null;
    StringBuffer msg_buf = new StringBuffer(_developerMessage(args_mismatch));
    String receiver_str;
    var level = (_invocation_type >> _InvocationMirror._CALL_SHIFT) &
        _InvocationMirror._CALL_MASK;
    if ( level == _InvocationMirror._TOP_LEVEL) {
      receiver_str = "top-level";
    } else {
      receiver_str = Error.safeToString(_receiver);
    }
    var memberName =
        (_memberName == null) ? "" : internal.Symbol.getUnmangledName(_memberName);
    var type = _invocation_type & _InvocationMirror._TYPE_MASK;
    if (type == _InvocationMirror._LOCAL_VAR) {
      msg_buf.write(
          "NoSuchMethodError: cannot assign to final variable '$memberName'");
    } else if (!args_mismatch) {
      msg_buf.write(
          "NoSuchMethodError: method not found: '$memberName'\n"
          "Receiver: $receiver_str\n"
          "Arguments: [$actual_buf]");
    } else {
      String actualParameters = actual_buf.toString();
      StringBuffer formal_buf = new StringBuffer();
      for (int i = 0; i < _existingArgumentNames.length; i++) {
        if (i > 0) {
          formal_buf.write(", ");
        }
        formal_buf.write(_existingArgumentNames[i]);
      }
      String formalParameters = formal_buf.toString();
      msg_buf.write(
          "NoSuchMethodError: incorrect number of arguments passed to "
          "method named '$memberName'\n"
          "Receiver: $receiver_str\n"
          "Tried calling: $memberName($actualParameters)\n"
          "Found: $memberName($formalParameters)");
    }
    return msg_buf.toString();
  }
}
