package Pcore::Ext::Class::Form;

use Pcore;

our $EXT_MAP = {    #
    panel => 'Ext.form.Panel',
};

sub EXT_panel ($ext) {
    return {
        editModel        => undef,
        canResetForm     => \1,
        canSaveForm      => \1,
        commitFormOnSave => \0,
        closeAfterSave   => \1,

        viewModel => { data => { formIsDirty => \0 } },

        referenceHolder => \1,

        layout => {
            type             => 'anchor',
            reserveScrollbar => \1,
        },
        autoScroll  => \1,
        bodyPadding => 10,
        minWidth    => 500,
        width       => 1,

        api        => {},
        baseParams => {},

        modelValidation  => \1,
        trackResetOnLoad => \1,
        fieldDefaults    => {
            anchor    => '100%',
            msgTarget => 'side',
        },

        fbar => {
            enableOverflow => \1,
            items          => [
                {   reference => 'reset_button',
                    text      => 'Reset form',
                    glyph     => 0xf0e2,
                    disabled  => \1,
                    bind      => { disabled => '{!formIsDirty}', },
                    handler   => 'resetForm',
                },
                '->',
                {   reference => 'save_button',
                    text      => 'Save',
                    glyph     => 0xf00c,
                    handler   => 'saveForm',
                },
                {   text    => 'Cancel',
                    glyph   => 0xf00d,
                    handler => 'cancelForm',
                }
            ]
        },

        defaultListenerScope => \1,

        listeners => {
            dirtyChange => $ext->js_func(
                [ 'form', 'dirty' ], <<'JS'
                    var viewmodel = this.getViewModel();

                    if (viewmodel) viewmodel.set('formIsDirty', dirty);
JS
            ),
        },

        initComponent => $ext->js_func(
            <<'JS'
                this.callParent(arguments);

                if (!this.editModel) {
                    this.canResetForm = false;
                    this.canSaveForm = false;
                } else {
                    this.getViewModel().set('editModel', this.editModel);
                }

                if (this.canResetForm) {
                    this.loadRecord(this.editModel);
                } else {
                    var resetButton = this.lookupReference('reset_button');

                    if (resetButton) {
                        resetButton.hide();
                        resetButton.setBind({});
                    }
                }

                if (!this.canSaveForm) {
                    var saveButton = this.lookupReference('save_button');

                    if (saveButton) {
                        saveButton.hide();
                        saveButton.setBind({});
                    }
                } else {
                    if (this.commitFormOnSave) {
                        if (this.editModel) {
                            if (this.editModel.phantom) {
                                this.baseParams.clientId = this.editModel.getId();

                                this.api.submit = this.editModel.getProxy().api.create;
                            } else {
                                this.baseParams.id = this.editModel.getId();

                                this.api.submit = this.editModel.getProxy().api.update;
                            }
                        }
                    }
                }
JS
        ),

        resetForm => $ext->js_func(
            <<'JS'
                if (this.canResetForm) {
                    this.reset();

                    this.getViewModel().get('editModel').reject();
                }
JS
        ),

        saveForm => $ext->js_func(
            <<'JS'
                if (!this.getForm().isValid()) return;

                if (!this.getForm().isDirty()) {
                    if (this.closeAfterSave) {
                        return this.destroy();
                    } else {
                        return;
                    }
                }

                if (this.commitFormOnSave) {
                    this._commitForm();
                } else {
                    this._commitModel();
                }
JS
        ),

        cancelForm => $ext->js_func(
            <<'JS'
                if (this.getForm().isDirty()) {
                    Ext.Msg.confirm('Discard changes?', 'Form was changed. Are you sure to close form and discard changes?', function (result) {
                        if (result == 'yes') {
                            this.getViewModel().get('editModel').reject();

                            this.destroy();
                        }
                    }, this);
                } else {
                    this.getViewModel().get('editModel').reject();

                    this.destroy();
                }
JS
        ),

        _commitForm => $ext->js_func(
            <<'JS'
                var model = this.getViewModel().get('editModel');

                this.getForm().submit({
                    waitMsg: 'Commit form...',
                    scope: this,
                    success: function (form, action) {
                        model.set(action.result.data[0]);

                        model.commit();

                        this.fireEvent('recordUpdated', model);

                        if (this.closeAfterSave) {
                            this.destroy();
                        } else {
                            if (this.canResetForm) {
                                this.loadRecord(model);
                            }
                        }
                    }
                });
JS
        ),

        _commitModel => $ext->js_func(
            <<'JS'
                var model = this.getViewModel().get('editModel');

                model.save({
                    scope: this,
                    success: function (models, operation, success) {
                        model.commit();

                        this.fireEvent('recordUpdated', model);

                        if (this.closeAfterSave) {
                            this.destroy();
                        } else {
                            if (this.canResetForm) {
                                this.loadRecord(model);
                            }
                        }
                    },
                    failure: function (models, operation, success) {
                        if (operation.getProxy().getReader().rawData.errors) {
                            var form = this.getForm();

                            form.markInvalid(operation.getProxy().getReader().rawData.errors);
                        }
                    }
                });
JS
        ),
    };
}

1;
__END__
=pod

=encoding utf8

=head1 NAME

Pcore::Ext::Class::Form

=head1 SYNOPSIS

=head1 DESCRIPTION

=head1 ATTRIBUTES

=head1 METHODS

=head1 SEE ALSO

=cut
