var CURRENT_PROTO = null;
Ext.namespace('FW', 'FW.Pages', 'FW.Widgets', 'FW.utils');
FW.CONSTANTS = {
    date_display_format : 'n/j/Y',
    datetime_display_format: 'n/j/Y g:i A T',
    empty_select_text: '--Select--'
}
var page;
Ext.QuickTips.init();

try { console.log('init console... done'); } catch(e) { console = { log: function() {} } }

Array.prototype.merge = function(e) {
    if(e instanceof Array) {
        for(var i=0; i < e.length; i++) { this.push(e[i]); }
    } else
        this.push(e);
    return this;
}
Array.prototype.grep = function(pred) {
    for(var i=0; i < this.length; i++) {
        if(pred(this[i]))
            return i;
    }
    return -1;
}
Array.prototype.last = function() {
    var len = this.length;
    if(len == 0)
        return null;
    return this[len-1];
}

Ext.num=function(n, default_val) {
    if(n == null)
        return default_val;
    n = Number(n);
    return (isNaN(n) ? default_val : n);
}
Ext.attach_delayed_handler=function(elem_id, handler, scope, evt, task) {
    var fn = function(elem_id, handler, evt, task) {
        var e = Ext.get(elem_id);
        if(e) {
            evt = evt || 'click';
            e.on(evt, handler, this, {stopEvent: true});
        } else {
            task = task || new Ext.util.DelayedTask();
            task.delay(500, fn, this, [elem_id, handler, evt, task]);
        }
    };
    fn.call(scope, elem_id, handler, evt, task);
}
Ext.apply(Ext.EventObject, {
    within_el:function(el) {
        el = Ext.get(el);
        if(!el)
            return false;
        var evt_xy = this.getXY();
        var evt_x = evt_xy[0];
        var evt_y = evt_xy[1];
        console.log("EVT "+ evt_x + ':'+evt_y+' EL '+ el.getLeft() + ':' + el.getRight() + ':' +  el.getTop()
                    +':'+ el.getBottom() );
        return (evt_x > el.getLeft() && evt_x < el.getRight() && evt_y > el.getTop() && evt_y < el.getBottom());
    }
});
Ext.override(Ext.Component, {
    create_listener_sequence: function(evt_name, listeners, wrapper_fn, wrapper_scope) {
        wrapper_scope = wrapper_scope || this;
        if(!listeners[evt_name]) {
            listeners[evt_name] = {
                fn: wrapper_fn,
                scope:wrapper_scope
            };
        } else {
            var orig_fn = listeners[evt_name].fn;
            var orig_scope = listeners[evt_name].scope;
            listeners[evt_name] = {
                fn: wrapper_fn.createSequence(orig_fn, orig_scope),
                scope:wrapper_scope
            }
        }
    }
});

FW.utils.AjaxUtils = {};
FW.utils.AjaxUtils.ajax_parse_response=function(resp) {
    if(resp._fw_decoded)
        return resp;
    var r = (resp.result != null) ? resp.result : Ext.decode(resp.responseText);
    r._fw_decoded = true;
    if(r.performance) {
        var perf_span = Ext.get('__performance_stats');
        if(perf_span && r.performance.db_stats) {
            perf_span.update(r.performance.db_stats);
        }
    }
    return r;
}

FW.utils.AjaxUtils.ajax_process_errors = function(resp) {
    resp    = this.ajax_parse_response(resp);
    var err_obj = resp.error_obj;
    var page_errors = err_obj.page;
    var fields  = err_obj.fields;
    if(!page_errors && (fields instanceof Object)) {
        page_errors = '';
        for(var i in fields) {
           page_errors += '<li>' + i + ": " + fields[i] + "</li>";
        }
    }
    if(page_errors)
    page_errors = '<ul>'+page_errors+'</ul>';

    var to_focus=null;
    if(fields instanceof Object) {
        for(var k in fields) {
            var cmp = Ext.getCmp(k);
            if(cmp) {
                cmp.markInvalid(fields[k]);
                to_focus = to_focus || cmp;
            }
        }
    } else if(fields instanceof Array) {
        Ext.each(fields, function(f) {
            var cmp = Ext.getCmp(f);
            if(cmp) {
                cmp.markInvalid();
                to_focus = to_focus || cmp;
            }
        });
    }
    if(page_errors)
        this.msg_obj().showError(page_errors, {
            handler: function() {
                if(to_focus)
                    to_focus.focus();
            }
        });
}

FW.utils.AjaxUtils.ajax_process_notice = function(resp, config) {
    resp        = this.ajax_parse_response(resp);
    var err_obj = resp.error_obj;

    config = config || {};
    if(err_obj.notice || resp.redirect_to) {
        if(resp.redirect_to || resp.goto_tab) {
            if(err_obj.notice) {
                // both redirect_to and notice
                config.handler = config.handler || function(to_where) {
                    resp.goto_tab ? this.goto_tab(resp.goto_tab) : this.refresh_page(resp.redirect_to);
                };
                config.scope = this;
            } else {
                resp.goto_tab ? this.goto_tab(resp.goto_tab) : this.refresh_page(resp.redirect_to);
            }
        }
        if (err_obj.notice)
            this.msg_obj().showMessage(err_obj.notice, config);
    }
}

FW.utils.AjaxUtils.ajax_load_javascript_fragments = function(resp) {
    resp    = this.ajax_parse_response(resp);
    if(resp.js_fragments) {
        Ext.each(resp.js_fragments, function(js) {
            eval('('+js+')');
        });
    }
}

FW.utils.AjaxUtils.ajax_handle_response = function(resp) {
    resp    = this.ajax_parse_response(resp);

    this.ajax_process_errors(resp);
    this.ajax_process_notice(resp);
    this.ajax_load_javascript_fragments(resp);
    return resp;
}

FW.utils.AjaxUtils.ajax_handle_failure = function(resp,options) {
    Ext.Msg.alert("ajax connection failure");
}
////

FW.utils.FormUtils = {};
FW.utils.FormUtils.form_submit_ajax=function(config) {
    Ext.each(Ext.DomQuery.select("*[class*='bad-input']", Ext.get(config.form_id).dom), function(e) {
         Ext.get(e.getAttribute('id')).removeClass('bad-input');
    }, this);
    Ext.get(config.mask_el || config.form_id).mask(config.wait_msg || "Submitting...");

    Ext.Ajax.request({
        url: config.url,
        form: config.form_id,
        params: (config.params||{}),
        method: (config.method||'POST'),
        success: this.bind(function(resp) {
            Ext.get(config.mask_el || config.form_id).unmask();
            resp = this.ajax_parse_response(resp);
            var fn = config.response ? config.response.fn : this.ajax_handle_response;
            fn.call(this, resp);
        }),
        failure: this.bind(function(resp) {
            this.ajax_process_errors(resp);
        }),
        scope: config.scope
    });
}

FW.utils.FormUtils.form_attach_form = function(config) {
    var form = Ext.get(config.form);
    var fields = form.dom.elements;
    var items  = [];
    config.buttons = config.buttons || {};
    config.radio_groups = {};

    var submit_btn, reset_btn, submit_cnf, buttons= {} ;
    var def_width = config.default_width;
    var focus_field;
    var form_type = config.form_type || 'form_panel';
    config.form_type = form_type;
    //Ext.each(fields, function(field) {
    for(var i=0; i < fields.length; i++) {
        var field = fields[i];
        var node_type = field.nodeName.toLowerCase();
        var type      = field.type.toLowerCase() || 'text';
        if(type == 'file')
            config.fileUpload = true;
        var ext_field = null;
        var no_ext = field.getAttribute('no_ext');
        if(no_ext == null || no_ext == 0)
            ext_field = this.create_ext_elem(field, config);
        if(ext_field) {
            if(node_type == 'input' && (type == 'submit' || type == 'reset')) {
                buttons[field.getAttribute('id')] = {
                    btn: ext_field,
                    type: type
                };
            } else {
                items.merge(ext_field);
                if(focus_field == null) {
                    ext_field = (ext_field instanceof Array) ? ext_field[0] : ext_field;
                    focus_field = ext_field;
                }
            }
        }
    }

    config.url   = config.url || form.dom.action;
    config.method= form.dom.method || 'POST';
    config.focus_field = focus_field;

    delete config['form_type'];
    if(form_type == 'form_panel')
        form = this._create_form_panel(config, items, buttons);
    else if(form_type == 'basic_form')
        form = this._create_basic_form(config, items, buttons);

    return form;
}

FW.utils.FormUtils.form_load_values = function(form_cmp, values, prefix) {
    var form_values = {};
    var radio_values = [];
    for(var k in values) {
        var key = k;
        if(prefix) {
            key = prefix+'[' + k + ']';
        }
        // radios are very special since Ext.form.Radio.setValue seems to work only with true/false and also
        // while creating, it doesn't preseve the value. So, our convention is to assume the id if each Radio is
        // like [name]-[value] so eg. <input name='income' id='income-53' value='53'/>
//        var radios = document.getElementsByName(key);
//        if(radios && radios.length > 0 && radios[0].getAttribute('type') == 'radio') {
//            Ext.each(radios, function(radio) {
//                var radio_id = radio.getAttribute('id');
//                var value = radio_id.replace(/[^\d]+/,'') || '';
//                var ext_cmp = Ext.getCmp(radio_id);
//                if(ext_cmp) {
//                    radio_values.push(ext_cmp);
//                    radio_values.push(value == String(values[k]));
//                }
//            },this);
//        } else {
            form_values[key] = values[k];
//        }
    }
    if(form_cmp instanceof Ext.form.FormPanel)
            form_cmp = form_cmp.getForm();

    form_cmp.setValues(form_values);
    for(var i=0; i < radio_values.length; i+=2) {
        radio_values[i].setValue(radio_values[i+1]);
    }
}

FW.utils.FormUtils._create_basic_form = function(config,items,buttons) {
    var form = Ext.get(config.form);
    buttons  = buttons || {};
    delete config.radio_groups;

    var ext_form = new Ext.form.BasicForm(config.form, config);
    Ext.each(items, function(item) {
        ext_form.add(item);
    }, this);

    var orig_btns_config = config['buttons'] || {};

    for(var id in buttons) {
        var b     = buttons[id].btn;
        var f = Ext.get(id);
        var p = f.parent();
        f.remove();
        b.renderTo = p;
        b=new Ext.Button(b);
    }

    for(var i in orig_btns_config) {
        if(orig_btns_config[i] instanceof Object)
            orig_btns_config[i].form = ext_form;
    }
    config.form = ext_form;
    if(!config._no_enter_key)
        this._attach_enter_key(config.form, buttons);

    return ext_form;
}

FW.utils.FormUtils._create_form_panel = function(config, items, buttons) {
    var form = Ext.get(config.form);

    config.items = items;
    delete config.radio_groups;

    var orig_btns_config = config['buttons'] || {};
    var found_key=false;
    config.buttons = [];
    for(var i in buttons) {
        config.buttons.push(buttons[i].btn);
    }
    if(config.buttons.length == 0)
        delete config['buttons'];

    if(!config._no_render) {
        var ct = form.insertSibling();
        form.remove();
        config.renderTo = ct;
    }
    config.frame    = ('frame' in config) ? config.frame : true;

    Ext.form.Field.prototype.msgTarget = 'qtip';

    var focus_field = config.focus_field;
    Ext.each(['submit','reset','default_width','msgTarget', 'focus_field'], function(k) { delete config[k]; });
    config.buttonAlign   = config.buttonAlign || 'center';
    config.labelAlign    = config.labelAlign || 'right';
    config.waitMsgTarget = true;
    var form_panel = new Ext.form.FormPanel(config);

    for(var i in orig_btns_config) {
        if(orig_btns_config[i] instanceof Object)
            orig_btns_config[i].form = form_panel;
    }
    config.form = form_panel; // for reset handler
    if(focus_field)
        focus_field.focus.defer(1000);


    if(!config._no_enter_key)
        this._attach_enter_key(config.form.getForm(), buttons);
    return form_panel;
}

FW.utils.FormUtils._attach_enter_key=function(form, buttons) {
    if(form.getEl() == null)
        return;

    var submit_btn = null;
    for(var i in buttons) {
        if(buttons[i].type == 'submit') {
            submit_btn = buttons[i].btn;
            break;
        }
    }

    if(submit_btn && submit_btn.handler instanceof Function) {
        new Ext.KeyNav(form.getEl(), {
            enter: function(e) {
                var node_type = e.getTarget().nodeName.toLowerCase();
                if(node_type != 'textarea')
                    submit_btn.handler();
            }
        })
    }
}

FW.utils.FormUtils.create_ext_elem = function(field, config) {
    config = config || {};
    var node_type = field.nodeName.toLowerCase();
    var type      = field.type.toLowerCase() || 'text';
    var ext_attrs = field.getAttribute('ext_attrs');
    var form_type = config.form_type;
    if (ext_attrs) {
        if(!ext_attrs.match(/^\{/))
            ext_attrs = '{' + ext_attrs + '}';
        ext_attrs = Ext.util.JSON.decode(ext_attrs);
    } else {
        ext_attrs = {};
    }
    var custom_attrs = field.getAttribute('custom_attrs') ;
    if(custom_attrs) {
        if(!custom_attrs.match(/^\{/))
            custom_attrs = '{' + custom_attrs + '}';
        custom_attrs = Ext.util.JSON.decode(custom_attrs);
    }
    type = 'xtype' in ext_attrs ? ext_attrs.xtype : type;
    field.removeAttribute('ext_attrs');
    if(config.form_type == 'basic_form')
        ext_attrs.applyTo = field.getAttribute('id');
    this._merge_id_name(field);
    var ext_field = null;
    if (node_type) {
        if(node_type == 'input') {
            switch (type) {
            case 'text':
            case 'password':
            case 'file':
            case 'hidden':
                ext_attrs.inputType = type;
                this._apply_default_attrs(ext_attrs, config.default_width, field);
                if(!ext_attrs.width && config.default_width)
                    ext_attrs.width = config.default_width;

                if(ext_attrs.maxLength) {
                    field.setAttribute('maxlength', ext_attrs.maxLength);
                }
                this._attach_custom_attrs_listener(ext_attrs,custom_attrs);
                if(ext_attrs.vtype == 'integer' || ext_attrs.vtype == 'numeric') {
                    delete ext_attrs.vtype;
                    ext_field = new Ext.form.NumberField(ext_attrs);
                } else
                    ext_field = new Ext.form.TextField(ext_attrs);
                break;
            case 'radio':
                var listner_hash = '{' + (field.getAttribute('listeners') || '') + '}';
                var radio = {
                    inputValue: field.getAttribute('value'),
                    boxLabel: field.getAttribute('boxLabel'),
                    id: field.getAttribute('id'),
                    listeners: eval(String.format("({0})",listner_hash))
                };
                if(form_type == 'basic_form') {
                    radio['name'] = field.getAttribute('name');
                    var f = Ext.get(field);
                    var p = f.parent();
                    f.remove();
                    radio.renderTo = p;
                    this._attach_custom_attrs_listener(radio,custom_attrs);
                    ext_field = new Ext.form.Radio(radio);
                } else {
                    var grp_name  = field.getAttribute('name');
                    var radio_grp = config.radio_groups[grp_name];
                    if(!radio_grp) {
                        // first radio in the group has all info needed for the entire group
                        radio_grp = ext_attrs;
                        radio_grp.xtype = 'ux-radiogroup';
                        radio_grp.fieldLabel = field.getAttribute('label');
                        radio_grp.name  = grp_name;
                        Ext.applyIf(radio_grp, {horizontal:true});
                        radio_grp.radios = [radio];
                        config.radio_groups[grp_name] = radio_grp;
                        this._attach_custom_attrs_listener(radio_grp,custom_attrs);
                        ext_field = radio_grp;
                    } else {
                        this._attach_custom_attrs_listener(radio,custom_attrs);
                        radio_grp.radios.push(radio);
                        ext_field = null;
                    }
                }
                break;
            case 'datefield':
                this._apply_default_attrs(ext_attrs, null, field);
                ext_attrs.inputValue = field.getAttribute('value');
                ext_attrs.format = ext_attrs.format || FW.CONSTANTS.date_display_format;
                this._attach_custom_attrs_listener(ext_attrs,custom_attrs);
                ext_field = new Ext.form.DateField(ext_attrs);
                break;
            case 'checkbox':
                ext_attrs.inputType = type;
                this._apply_default_attrs(ext_attrs, null, field);
                ext_attrs.checked = field.getAttribute('checked') ? true : false;
                ext_attrs.inputValue = field.getAttribute('value');
                this._attach_custom_attrs_listener(ext_attrs,custom_attrs);
                ext_field = new Ext.form.Checkbox(ext_attrs);
                break;
            case 'submit':
                var btn_id = field.getAttribute('id');
                var btn_handler = config.buttons[btn_id] || {};
                config.buttons[btn_id] = btn_handler;
                btn_handler = (btn_handler instanceof Function) ? btn_handler : this._form_submit_form(btn_handler,config);
                ext_field = {
                    text: field.value,
                    id:btn_id,
                    handler: btn_handler,
                    scope:this
                };
                if(config.form_type == 'form_panel')
                    ext_field = new Ext.Button(ext_field);
                break;
            case 'reset':
                var reset_cnf  = config.reset || function() {
                    var basic_form = (config.form instanceof Ext.form.FormPanel ? config.form.getForm() : config.form );
                    basic_form.reset();
                };
                ext_field = {
                    text: field.value,
                    id: field.getAttribute('id'),
                    handler:reset_cnf
                };
                if(config.form_type == 'form_panel')
                    ext_field = new Ext.Button(ext_field);
                break;
            }
        } else if (node_type == 'textarea') {
            this._apply_default_attrs(ext_attrs, config.default_width, field);
            ext_attrs.value = field.value;
            this._attach_custom_attrs_listener(ext_attrs,custom_attrs);
            ext_field = new Ext.form.TextArea(ext_attrs);
        } else if (node_type == 'select') {
            ext_attrs.field = field;
            ext_attrs.form_type = config.form_type;
                this._attach_custom_attrs_listener(ext_attrs,custom_attrs);
            ext_field = field.getAttribute('multiple') ? new FW.Widgets.MultiSelect(ext_attrs) : new FW.Widgets.SingleSelect(ext_attrs);
        }
    }
    return ext_field;
}
FW.utils.FormUtils._attach_custom_attrs_listener = function(field_def, custom_attrs) {
    if(custom_attrs) {
        field_def.listeners = field_def.listeners || {};
        field_def.listeners.render = {
            fn: function(cmp) {
                for(var k in custom_attrs) {
                    cmp.getEl().dom.setAttribute(k, custom_attrs[k]);
                }
            },
            scope: this
        };
    }
}
FW.utils.FormUtils._apply_default_attrs = function(ext_attrs, def_width, field) {
    var l = field.getAttribute('label');
    if(l) {
        ext_attrs.fieldLabel = l;
    }

    Ext.each(['id','name','width','value','size'], function(attr) {
        if (field.getAttribute(attr))
            ext_attrs[attr] = field.getAttribute(attr) ;
    });
    if(!ext_attrs.width && def_width)
        ext_attrs.width = def_width;
}

FW.utils.FormUtils._merge_id_name = function(field) {
    var id   = field.getAttribute('id');
    var name = field.getAttribute('name');
    if(id && !name)
       name = id;
    if(name && !id)
       id = name;
    field.setAttribute('name',name);
    field.setAttribute('id',id);
}

FW.utils.FormUtils._form_submit_form = function(config, form_config) {
    form_config = form_config || {};
    return this.bind(function() {
        if(config.form instanceof Ext.form.FormPanel)
            config.form = config.form.getForm();
        if(!(config.form instanceof Ext.form.BasicForm))
            config.form = Ext.getCmp(config.form);// assume it's a string ID
        if(!config.form.isValid())
            return;
        var submit_opts = {
            method: 'POST',
            params:{authenticity_token: this.authenticity_token()},
            success: function(form,action) {
                this.toggle_msg_obj().hide_msg();
                var resp = this.ajax_parse_response(action);
                fn   = config.response;
                if(fn)
                    fn.call(this,resp,form);
                else {
                    this.ajax_handle_response(resp,form);
                    if(form_config.reset_after)
                        config.form.reset();
                }
            },
            failure: function(form,action) {
                this.toggle_msg_obj().hide_msg();
                var resp = this.ajax_parse_response(action);
                resp     = resp || {success: false};
                if(config.failure instanceof Function) {
                    config.failure.call(this,resp);
                } else if(config.response) {
                    config.response.call(this,resp,form);
                } else {
                    if(resp && !resp.success)
                        this.ajax_process_errors(resp);
                    else
                        this.ajax_handle_failure(resp);
                }
            },
            scope:this
        };
        Ext.each(['url','params','method'], function(p) {
            if(config[p]) {
                if(p == 'params')
                    Ext.apply(submit_opts[p], config[p]);
                else
                    submit_opts[p] = config[p];
            }
        });
        if(submit_opts['method'] == 'put' || submit_opts['method'] == 'delete') {
            submit_opts['_method'] = submit_opts['method'];
            submit_opts['method'] = 'POST';
        }

        var ret = true;
        if(config.before_submit instanceof Function) {
            ret = config.before_submit.call(this, config.form, submit_opts);
        }
        if(ret) {
            this.toggle_msg_obj().show_msg(config.wait_msg || 'Submitting...');
            config.form.submit(submit_opts);
        }
    });
}
// End of FormUtils

///
FW.utils.GridUtils = {};
FW.utils.GridUtils.grid_row_num_defn=function(args) {
 return {header:'#', width:25, fixed: true, align:'center', renderer: this.grid_row_number_renderer}
}
FW.utils.GridUtils.grid_row_number_renderer=function(cell_data, meta_data, record, row_index) { return row_index + 1; }
FW.utils.GridUtils.grid_create_grid = function(config) {
    return new FW.Widgets.EditorGrid(config);
}

FW.utils.GridUtils.grid_hide_header = function(gridcontainer_id) {
    var head        = Ext.DomQuery.select('head')[0];
    var selector    = '#' + gridcontainer_id + ' * tr[class=x-grid3-hd-row] {' +
                      'display:none;' +
                      '}';
    Ext.DomHelper.append(head, "<style type='text/css' id='" + gridcontainer_id + '_style'+"'>" + selector + "</style>");
}

FW.utils.GridUtils.grid_show_header = function(gridcontainer_id) {
    var style        = Ext.DomQuery.select("head/style[id=" + gridcontainer_id + '_style' + ']')[0];
    if(style)
        Ext.get(style).remove();
}
FW.utils.GridUtils.grid_is_header_visible = function(gridcontainer_id) {
    var style        = Ext.DomQuery.select("head/style[id=" + gridcontainer_id + '_style' + ']')[0];
    return style ? false : true;

}

FW.utils.GridUtils.grid_get_selected_ids=function(grid_panel) {
    var sm = grid_panel.getSelectionModel();
    var records = sm.getSelections();
    var id_array = [];
    Ext.each(records, function(r) {
            id_array.push(r.id);
    });
    return id_array;
}

// End of GridUtils

Ext.grid.TableGrid = function(table, config) {
    config = config || {};
    var cf = config.fields || [], ch = config.columns || [];
    table = Ext.get(table);

    var ct = table.insertSibling();

    var fields = [], cols = [];
    var headers = table.query("thead th");
    for (var i = 0, h; h = headers[i]; i++) {
        var text = h.innerHTML;
        var name = 'tcol-'+i;

        fields.push(Ext.applyIf(cf[i] || {}, {
            name: name,
            mapping: 'td:nth('+(i+1)+')/@innerHTML'
        }));

        cols.push(Ext.applyIf(ch[i] || {}, {
            'header': text,
            'dataIndex': name,
            'width': h.offsetWidth,
            'tooltip': h.title,
            'sortable': true
        }));
    }

    var ds  = new Ext.data.Store({
        reader: new Ext.data.XmlReader({
            record:'tbody tr'
        }, fields)
    });

    ds.loadData(table.dom);

    var cm = new Ext.grid.ColumnModel(cols);
    if(config.width || config.height){
        ct.setSize(config.width || 'auto', config.height || 'auto');
    }
    config.id = config.id || table.id;
    if(config.remove !== false){
        table.remove();
    }

    console.log(config);

    this._my_table = ct;
    Ext.grid.TableGrid.superclass.constructor.call(this,
                                                   Ext.applyIf(config, {
                                                       store: ds,
                                                       colModel: cm,
                                                       'sm': new Ext.grid.RowSelectionModel(),
                                                       autoHeight:true,
                                                       autoWidth:true
                                                   }
                                                   )
    );
}

Ext.extend(Ext.grid.TableGrid, Ext.grid.GridPanel, {
    render: function() {
        Ext.grid.TableGrid.superclass.render.call(this,this._my_table);
    }
});

///
String.prototype.underscore = function() {
    return this.replace(/\s+/,'_').toLowerCase();
}
String.prototype.boolean_to_yn=function() {
    return this ? "Yes" : "No";
}
String.prototype.camelize=function() {
    if(this.length == 0)
        return this;

    var cache = page.camelize_cache;
    if(cache && cache[this])
        return cache[this];

    var capitalized = [];
    Ext.each(this.toLowerCase().split(/_|\s+|-/), function(tok) {
        capitalized.push(tok.replace(/^./, tok.charAt(0).toUpperCase()));
    }, this);
    return capitalized.join(' ');
}

String.prototype.number_with_delimiter=function(delimiter, separator) {
    var n = Number(this);
    var is_neg = (n < 0);
    if(n < 0)
        n = n*-1;
    var ret = Ext.util.Format.usMoney(n).replace(/^\$/,'');
    ret = is_neg ? ('-'+ret) : ret;
    return ret;
}

String.prototype.number_with_precision=function(precision) {
    precision = precision == null ? 3 : precision;
    ret = this;
    try {
        ret = ret*1.0;
        ret = ret.toFixed(precision);
    } catch(e) {}
    return ret;
}

String.prototype.number_to_currency=function(options) {
    options       = options || {};
    var precision = ('precision' in options) ? options["precision"] : 2;
    var unit      = ('units' in options) ?  options["units"] : "$";
    var separator = precision > 0 ? (options["separator"] || ".") : "";
    var suppress_decimal_zeros = ('suppress_decimal_zeros' in options) ? options.suppress_decimal_zeros : true;
    var delimiter = options["delimiter"] || ",";
    var ret = this;
    try {
        var parts = this.number_with_precision(precision).split('.');
        ret = unit + parts[0].number_with_delimiter(delimiter).replace(/\.0+/,''); // usMoney always appends .00
        var after_decimal = parts.length > 1 ? Number(parts[1]) : 0;
        if(after_decimal != 0)
            ret += separator + parts[1];
        else if (!suppress_decimal_zeros)
            ret += separator + parts[1];
    } catch(e) {}
    return ret;
}

// End of StringUtils
