import {UnauthorizedError, isUnauthorizedError} from 'ember-ajax/errors';
import {inject as injectService} from '@ember/service';
import AjaxService from '@bennerinformatics/ember-fw/services/ajax';
import RSVP from 'rsvp';

/**
 * This service extends both [Ember-FW's AjaxService](https://linformatics.bitbucket.io/docs/addons/client-api/ember-fw/classes/AjaxService.html),
 * and the [Ember AjaxService](https://github.com/ember-cli/ember-ajax#ember-ajax), which is Ember-FW's base. The main thing that Ember FW GC's AjaxService
 * adds to these other two is functionality with Group Control authentication. It rewrites all of the
 * [HTTP-verbed methods](https://github.com/ember-cli/ember-ajax?tab=readme-ov-file#http-verbed-methods) to account for Group Control authentication,
 * and throws an `UnauthorizedError` if the user is not logged in. For the developer within the apps, however, the AjaxService will function almost identically
 * to the EmberAjaxService, and the Ember-FW AjaxService. Because of this there is no need to document each of the methods, which are documented by EmberAjaxService.
 * The only thing that is added for the developer to call different than EmberAjaxService is the third parameter `defaultBehavior` (default is false), which was added
 * to all the HTTP-verbed methods. All this will do is skip the user authentication added by Ember FW GC, and instead use the default HTTP-verbed method from
 * EmberAjaxService.
 *
 * For a basic example of how to implement the config (and ajax) service at the basic level, see our
 * [Conceptual Introduction - Advanced Topics](https://linformatics.bitbucket.io/docs/training/intro/advanced/#ajax-requests).
 * @public
 * @class AjaxService
 * @extends @bennerinformatics/ember-fw/services/ajax
 * @module Services
 */
export default AjaxService.extend({
    session: injectService(),

    handleResponse(status, headers, payload) {
        if (status === 401 && payload.error && this.get('session.isAuthenticated')) {
            this.get('session').triggerReAuthenticate();
            return new UnauthorizedError();
        }

        return this._super(...arguments);
    },

    request(url, options, defaultBehavior = false) {
        if (defaultBehavior) {
            return this._super(url, options);
        }

        return new RSVP.Promise((resolve, reject) => {
            return this.request(url, options, true).then(resolve).catch((error) => {
                if (!isUnauthorizedError(error)) {
                    return reject(error);
                }

                this.get('session').on('after-re-login', () => this.request(url, options).then(resolve));
            });
        });
    },

    post(url, options, defaultBehavior = false) {
        return this.request(url, this._addTypeToOptionsFor(options, 'POST'), defaultBehavior);
    },

    put(url, options, defaultBehavior = false) {
        return this.request(url, this._addTypeToOptionsFor(options, 'PUT'), defaultBehavior);
    },

    patch(url, options, defaultBehavior = false) {
        return this.request(url, this._addTypeToOptionsFor(options, 'PATCH'), defaultBehavior);
    },

    del(url, options, defaultBehavior = false) {
        return this.request(url, this._addTypeToOptionsFor(options, 'DELETE'), defaultBehavior);
    }
});