export interface AsyncFormPostModuleOptions {
    getPostDataCallback?: ($form: JQuery) => object;
    beforeAjaxCallback?: ($form: JQuery) => void;
    successCallback?: ($form: JQuery, successData: any) => void;
    errorCallback?: ($form: JQuery, errorData: any) => void;
    postUrl?: string;
    performAjax?: boolean;
    formValidCallback?: ($form: JQuery) => void;
    formInvalidCallback?: ($form: JQuery) => void;
}


export default class AsyncFormPostModule {

    $form: JQuery;
    options: AsyncFormPostModuleOptions;

    constructor($formElement: JQuery, options: AsyncFormPostModuleOptions) {

        if($formElement.length !== 1) {
            throw Error("Cannot initialise AsyncFormPostModule with the given jQuery element, since the element count was: " + $formElement.length);
        }

        this.$form = $formElement;

        if(options.performAjax === undefined)
            options.performAjax = true;

        this.options = options;

        let isInitialised = this.$form.data("async-form-post-initialised");

        if (isInitialised !== true) {
            this.initialiseModule();
        }
    }

    private initialiseModule() {

        let self = this;
        this.$form.submit(function (event) {
            event.preventDefault();

            self.$form.validate();

            let formIsValid = self.$form.valid()
            if (formIsValid !== true) {

                if(self.options.formInvalidCallback !== undefined) {
                    self.options.formInvalidCallback(self.$form);
                }

                return;
            }

            if(self.options.formValidCallback !== undefined) {
                self.options.formValidCallback(self.$form);
            }

            if(self.options.performAjax === true) {
                let asyncPostUrl = self.options.postUrl;

                if (asyncPostUrl === undefined || asyncPostUrl.length <= 0)
                    asyncPostUrl = self.$form.data("async-form-post-url");

                if (asyncPostUrl === undefined || asyncPostUrl.length <= 0)
                    asyncPostUrl = self.$form.prop("action");

                let postData = self.options.getPostDataCallback(self.$form);

                if (self.options.beforeAjaxCallback !== undefined) {
                    self.options.beforeAjaxCallback(self.$form);
                }

                $.ajax({
                    type: "POST",
                    url: asyncPostUrl,
                    data: postData,
                }).fail(function(failData) {
                    if (self.options.errorCallback !== undefined) {
                        self.options.errorCallback(self.$form, failData);
                    }
                }).done(function (successData) {
                    if (self.options.successCallback !== undefined) {
                        self.options.successCallback(self.$form, successData);
                    }
                });
            }            
        });

        this.$form.data("async-form-post-initialised", true);
    }

}