Ext.ns('FW.Widgets.form.FormPanel');
FW.Widgets.form.FormPanel=function(config) {
    config.events = config.events || [];
    config.events.push('after_save', 'after_edit_values_load');
    this.addEvents(config.events);
    delete config.events;
    FW.Widgets.form.FormPanel.superclass.constructor.call(this,config);
}
Ext.extend(FW.Widgets.form.FormPanel, Ext.form.FormPanel);
Ext.reg('fw.widgets.form.formpanel',FW.Widgets.form.FormPanel);
CURRENT_PROTO=FW.Widgets.form.FormPanel.prototype;
FW.Widgets.form.FormPanel.form_error='Please correct Invalid Fields';

CURRENT_PROTO.initComponent=function() {
    var idx = 0;
    var root = this;
    if(this.form_def_root) {
        root = eval(this.form_def_root);
    }
    root.defaults = root.defaults || {};
    root.defaults.xtype = root.defaults.xtype || 'textfield';
    var name_re = root.name_prefix ? new RegExp(root.name_prefix + '\\[\\w+\\]') : null;
    Ext.each(root.items, function(i) {
        if(i.maxLength != null) {
            i.listeners = i.listeners || {};
            this.create_listener_sequence('render',i.listeners, function(c) {
                    c.el.dom.setAttribute('maxlength',i.maxLength);
                    if(idx == 0)
                        c.focus.defer(1000,c);
            }, this);
        }
        if(i.name && Ext.isEmpty(i.fieldLabel,false)) {
           i.fieldLabel = i.name.camelize();
        }
        if(i.name && name_re && !i.name.match(name_re)) {
            i.name = String.format("{0}[{1}]", root.name_prefix, i.name);
        }
        var allow_blank = Ext.isEmpty(i.allowBlank) ? root.defaults.allowBlank : i.allowBlank;
        if( !Ext.isEmpty(allow_blank) && !allow_blank ) {
            i.fieldLabel = i.fieldLabel+'*';
        }
        if(idx == 0 ) {
            i.listeners = i.listeners || {};
            this.create_listener_sequence('render', i.listeners, function(c) {
                    c.focus.defer(1000,c);
            }, this);
        }
        idx++;
    },this);
    if(root.edit_url)
        root.items = this._add_edit_wait_el(root.items);
    Ext.each((root.buttons || []), function(b) {
        b.scope = b.scope || this;
    },this);
    root.buttonAlign = root.buttonAlign || 'center';
    root.labelAlign = root.labelAlign || 'left';
    root.border = root.border || false;
    root.frame = root.frame || true;
    if(Ext.isEmpty(root.cls))
        root.cls = 'fw-widgets-form-formpanel';
    else
        root.cls += ' fw-widgets-form-formpanel';
    FW.Widgets.form.FormPanel.superclass.initComponent.call( this );
}
//CURRENT_PROTO.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
//        }
//    }
//}

CURRENT_PROTO.afterRender=function() {
    FW.Widgets.form.FormPanel.superclass.afterRender.call( this );
    if(this.edit_url)
        this._load_edit_values();
    var key_nav = null;
    Ext.each((this.buttons || []), function(b) {
        if(b.enter_key || !key_nav) {
            key_nav = new Ext.KeyNav(this.getForm().getEl(), {
            enter: function(e) {
                var node_type = e.getTarget().nodeName.toLowerCase();
                if(node_type != 'textarea')
                    b.handler.call(b.scope);
            }
            })
        }
    }, this);
}

CURRENT_PROTO._add_edit_wait_el=function(form_items) {
    var defaults = this.defaults || {};
    delete this.defaults;
    this.defaults = {border:false};
    if(!this.height) {
        throw new Error('formPanel needs a height to show Retrieving message in edit mode');
    }
    var items = [
        {
            layout: 'border',
            width: this.width,
            height: this.height ,
            defaults:{border:false},
            items: [
                {region:'north', height: 20, id: this.child_id('status'), html: '<div>Retrieving...</div>',
                    bodyStyle: "padding-bottom:5px;text-align:center;"
                },
                {
                    region:'center',
                    layout:'form',
                    defaults: defaults,
                    items: form_items
                }
            ]
        }
    ];
    return items;
}

CURRENT_PROTO._load_edit_values=function() {
    this.xhr({
        url: this.edit_url,
        method:'GET',
        success: function(r) {
            r = FW.utils.AjaxUtils.ajax_parse_response.call(this,r);
            if(r.success) {
                this.load_values(r.page_data[this.edit_data_root]);
                this.child_cmp('status').destroy();
                this.doLayout();
            }
        }
    });
}
CURRENT_PROTO.submit=function(config) {
    if(!config.url)
        throw new Error("form submit must have an URL");
    var form = this.getForm();
    if(!form.isValid()) {
        page.msg_obj().show_error(FW.Widgets.form.FormPanel.form_error);
        return;
    }
    page.toggle_msg_obj().show_msg('', 'Working...');
    config.url = page.url(config.url);
    form.clearInvalid();

    var form_this = this;
    var success_fn = config.success;
    config.success = function(form,action) {
        page.toggle_msg_obj().hide_msg();
        var resp = FW.utils.AjaxUtils.ajax_parse_response.call(this,action);
        if(!resp.success) {
            this._show_errors(resp);
        }
        if(success_fn)
            success_fn.call( (config.scope || this),resp);
        form_this.fireEvent('after_save', resp);
    };
    config.failure = function(form,action) {
        page.toggle_msg_obj().hide_msg();
        console.log("Failure in form submit");
        var resp = FW.utils.AjaxUtils.ajax_parse_response.call(this,action);
        form_this._show_errors(resp);
    };
    config.method =  config.method || (this.edit_url ? 'PUT' : 'POST');
    config.method = config.method.toUpperCase();
    if(config.method.match(/^(PUT|DELETE)$/)) {
        var m = config.method;
        config.method = 'POST';
        config.params = config.params || {};
        config.params['_method'] = m;
    }
    if(config.method != 'POST')
        throw new Error("Form Must be submitted using POST");

    config.scope = config.scope || this;
    form.submit(config);
}

CURRENT_PROTO.load_values = function(values) {
    var form_values = {};
    for(var k in values) {
        var key = k;
        if(this.name_prefix) {
            key = this.name_prefix+'[' + k + ']';
        }
        form_values[key] = values[k];
    }
    this.getForm().setValues(form_values);
    this.fireEvent('after_edit_values_load', form_values);
}
CURRENT_PROTO.find_field = function(prefixed_name) {
    return null;
}
CURRENT_PROTO._show_errors=function(resp) {
    resp = resp || {
        error_obj: null
    };
    var form = this.getForm();
    if(resp.error_obj.page) {
        page.msg_obj().show_error(resp.error_obj.page);
    }
    resp.error_obj.fields = resp.error_obj.fields || {};
    var show_page_error = false;
    for( var k in resp.error_obj.fields) {
        var prefixed_name = this.name_prefix ? String.format("{0}[{1}]", this.name_prefix, k) : k;
        var f = form.findField(k) || form.findField( prefixed_name ) || this.find_field(prefixed_name);
        if(f) {
            f.markInvalid(resp.error_obj.fields[k]);
            show_page_error = true;
        }
    }
    if(show_page_error)
        page.msg_obj().show_error(FW.Widgets.form.FormPanel.form_error);
}
