    // @tag foundation,core
    // @require ../class/Loader.js
    // @define Ext.Error

    /**
     * @author Brian Moeskau <brian@sencha.com>
     * @docauthor Brian Moeskau <brian@sencha.com>
     *
     * A wrapper class for the native JavaScript Error object that adds a few useful capabilities for handling
     * errors in an Ext application. When you use Ext.Error to {@link #raise} an error from within any class that
     * uses the Ext 4 class system, the Error class can automatically add the source class and method from which
     * the error was raised. It also includes logic to automatically log the error to the console, if available,
     * with additional metadata about the error. In all cases, the error will always be thrown at the end so that
     * execution will halt.
     *
     * Ext.Error also offers a global error {@link #handle handling} method that can be overridden in order to
     * handle application-wide errors in a single spot. You can optionally {@link #ignore} errors altogether,
     * although in a real application it's usually a better idea to override the handling function and perform
     * logging or some other method of reporting the errors in a way that is meaningful to the application.
     *
     * At its simplest you can simply raise an error as a simple string from within any code:
     *
     * Example usage:
     *
     *     Ext.Error.raise('Something bad happened!');
     *
     * If raised from plain JavaScript code, the error will be logged to the console (if available) and the message
     * displayed. In most cases however you'll be raising errors from within a class, and it may often be useful to add
     * additional metadata about the error being raised.  The {@link #raise} method can also take a config object.
     * In this form the `msg` attribute becomes the error description, and any other data added to the config gets
     * added to the error object and, if the console is available, logged to the console for inspection.
     *
     * Example usage:
     *
     *     Ext.define('Ext.Foo', {
     *         doSomething: function(option){
     *             if (someCondition === false) {
     *                 Ext.Error.raise({
     *                     msg: 'You cannot do that!',
     *                     option: option,   // whatever was passed into the method
     *                     'error code': 100 // other arbitrary info
     *                 });
     *             }
     *         }
     *     });
     *
     * If a console is available (that supports the `console.dir` function) you'll see console output like:
     *
     *     An error was raised with the following data:
     *     option:         Object { foo: "bar"}
     *         foo:        "bar"
     *     error code:     100
     *     msg:            "You cannot do that!"
     *     sourceClass:   "Ext.Foo"
     *     sourceMethod:  "doSomething"
     *
     *     uncaught exception: You cannot do that!
     *
     * As you can see, the error will report exactly where it was raised and will include as much information as the
     * raising code can usefully provide.
     *
     * If you want to handle all application errors globally you can simply override the static {@link #handle} method
     * and provide whatever handling logic you need. If the method returns true then the error is considered handled
     * and will not be thrown to the browser. If anything but true is returned then the error will be thrown normally.
     *
     * Example usage:
     *
     *     Ext.Error.handle = function(err) {
     *         if (err.someProperty == 'NotReallyAnError') {
     *             // maybe log something to the application here if applicable
     *             return true;
     *         }
     *         // any non-true return value (including none) will cause the error to be thrown
     *     }
     *
     */
    Ext.Error = Ext.extend(Error, {
        statics: {
            /**
             * @property {Boolean} ignore
             * Static flag that can be used to globally disable error reporting to the browser if set to true
             * (defaults to false). Note that if you ignore Ext errors it's likely that some other code may fail
             * and throw a native JavaScript error thereafter, so use with caution. In most cases it will probably
             * be preferable to supply a custom error {@link #handle handling} function instead.
             *
             * Example usage:
             *
             *     Ext.Error.ignore = true;
             *
             * @static
             */
            ignore: false,

            /**
             * @property {Boolean} notify
             * Static flag that can be used to globally control error notification to the user. Unlike
             * Ex.Error.ignore, this does not effect exceptions. They are still thrown. This value can be
             * set to false to disable the alert notification (default is true for IE6 and IE7).
             *
             * Only the first error will generate an alert. Internally this flag is set to false when the
             * first error occurs prior to displaying the alert.
             *
             * This flag is not used in a release build.
             *
             * Example usage:
             *
             *     Ext.Error.notify = false;
             *
             * @static
             */
            //notify: Ext.isIE6 || Ext.isIE7,

            /**
             * Raise an error that can include additional data and supports automatic console logging if available.
             * You can pass a string error message or an object with the `msg` attribute which will be used as the
             * error message. The object can contain any other name-value attributes (or objects) to be logged
             * along with the error.
             *
             * Note that after displaying the error message a JavaScript error will ultimately be thrown so that
             * execution will halt.
             *
             * Example usage:
             *
             *     Ext.Error.raise('A simple string error message');
             *
             *     // or...
             *
             *     Ext.define('Ext.Foo', {
             *         doSomething: function(option){
             *             if (someCondition === false) {
             *                 Ext.Error.raise({
             *                     msg: 'You cannot do that!',
             *                     option: option,   // whatever was passed into the method
             *                     'error code': 100 // other arbitrary info
             *                 });
             *             }
             *         }
             *     });
             *
             * @param {String/Object} err The error message string, or an object containing the attribute "msg" that will be
             * used as the error message. Any other data included in the object will also be logged to the browser console,
             * if available.
             * @static
             */
            raise: function(err){
                err = err || {};
                if (Ext.isString(err)) {
                    err = { msg: err };
                }

                var method = this.raise.caller,
                    msg;

                if (method) {
                    if (method.$name) {
                        err.sourceMethod = method.$name;
                    }
                    if (method.$owner) {
                        err.sourceClass = method.$owner.$className;
                    }
                }

                if (Ext.Error.handle(err) !== true) {
                    msg = Ext.Error.prototype.toString.call(err);

                    Ext.log({
                        msg: msg,
                        level: 'error',
                        dump: err,
                        stack: true
                    });

                    throw new Ext.Error(err);
                }
            },

            /**
             * Globally handle any Ext errors that may be raised, optionally providing custom logic to
             * handle different errors individually. Return true from the function to bypass throwing the
             * error to the browser, otherwise the error will be thrown and execution will halt.
             *
             * Example usage:
             *
             *     Ext.Error.handle = function(err) {
             *         if (err.someProperty == 'NotReallyAnError') {
             *             // maybe log something to the application here if applicable
             *             return true;
             *         }
             *         // any non-true return value (including none) will cause the error to be thrown
             *     }
             *
             * @param {Ext.Error} err The Ext.Error object being raised. It will contain any attributes that were originally
             * raised with it, plus properties about the method and class from which the error originated (if raised from a
             * class that uses the Ext 4 class system).
             * @static
             */
            handle: function(){
                return Ext.Error.ignore;
            }
        },

        // This is the standard property that is the name of the constructor.
        name: 'Ext.Error',

        /**
         * Creates new Error object.
         * @param {String/Object} config The error message string, or an object containing the
         * attribute "msg" that will be used as the error message. Any other data included in
         * the object will be applied to the error instance and logged to the browser console, if available.
         */
        constructor: function(config){
            if (Ext.isString(config)) {
                config = { msg: config };
            }

            var me = this;

            Ext.apply(me, config);

            me.message = me.message || me.msg; // 'message' is standard ('msg' is non-standard)
            // note: the above does not work in old WebKit (me.message is readonly) (Safari 4)
        },

        /**
         * Provides a custom string representation of the error object. This is an override of the base JavaScript
         * `Object.toString` method, which is useful so that when logged to the browser console, an error object will
         * be displayed with a useful message instead of `[object Object]`, the default `toString` result.
         *
         * The default implementation will include the error message along with the raising class and method, if available,
         * but this can be overridden with a custom implementation either at the prototype level (for all errors) or on
         * a particular error instance, if you want to provide a custom description that will show up in the console.
         * @return {String} The error message. If raised from within the Ext 4 class system, the error message will also
         * include the raising class and method names, if available.
         */
        toString: function(){
            var me = this,
                className = me.sourceClass ? me.sourceClass : '',
                methodName = me.sourceMethod ? '.' + me.sourceMethod + '(): ' : '',
                msg = me.msg || '(No description provided)';

            return className + methodName + msg;
        }
    });

    /*
     * Create a function that will throw an error if called (in debug mode) with a message that
     * indicates the method has been removed.
     * @param {String} suggestion Optional text to include in the message (a workaround perhaps).
     * @return {Function} The generated function.
     * @private
     */
    Ext.deprecated = function (suggestion) {
        //<debug>
        if (!suggestion) {
            suggestion = '';
        }

        function fail () {
            Ext.Error.raise('The method "' + fail.$owner.$className + '.' + fail.$name +
                    '" has been removed. ' + suggestion);
        }

        return fail;
        //</debug>
        return Ext.emptyFn;
    };

    /*
     * This mechanism is used to notify the user of the first error encountered on the page. This
     * was previously internal to Ext.Error.raise and is a desirable feature since errors often
     * slip silently under the radar. It cannot live in Ext.Error.raise since there are times
     * where exceptions are handled in a try/catch.
     */
    //<debug>
    (function () {
        var timer, errors = 0,
            win = Ext.global,
            msg;

        if (typeof window === 'undefined') {
            return; // build system or some such environment...
        }

        // This method is called to notify the user of the current error status.
        function notify () {
            var counters = Ext.log.counters,
                supports = Ext.supports,
                hasOnError = supports && supports.WindowOnError; // TODO - timing

            // Put log counters to the status bar (for most browsers):
            if (counters && (counters.error + counters.warn + counters.info + counters.log)) {
                msg = [ 'Logged Errors:',counters.error, 'Warnings:',counters.warn,
                            'Info:',counters.info, 'Log:',counters.log].join(' ');
                if (errors) {
                    msg = '*** Errors: ' + errors + ' - ' + msg;
                } else if (counters.error) {
                    msg = '*** ' + msg;
                }
                win.status = msg;
            }

            // Display an alert on the first error:
            if (!Ext.isDefined(Ext.Error.notify)) {
                Ext.Error.notify = Ext.isIE6 || Ext.isIE7; // TODO - timing
            }
            if (Ext.Error.notify && (hasOnError ? errors : (counters && counters.error))) {
                Ext.Error.notify = false;

                if (timer) {
                    win.clearInterval(timer); // ticks can queue up so stop...
                    timer = null;
                }

                alert('Unhandled error on page: See console or log');
                poll();
            }
        }

        // Sets up polling loop. This is the only way to know about errors in some browsers
        // (Opera/Safari) and is the only way to update the status bar for warnings and other
        // non-errors.
        function poll () {
            timer = win.setInterval(notify, 1000);
        }

        // window.onerror sounds ideal but it prevents the built-in error dialog from doing
        // its (better) thing.
        poll();
    }());
    //</debug>