import Controller from '@ember/controller';
import RSVP from 'rsvp';
import {
    VersionMismatchError,
    isVersionMismatchError
} from 'ghost-admin/services/ajax';
import {alias} from '@ember/object/computed';
import {isArray as isEmberArray} from '@ember/array';
import {inject as service} from '@ember/service';
import {task} from 'ember-concurrency';

export default Controller.extend({
    ajax: service(),
    config: service(),
    ghostPaths: service(),
    notifications: service(),
    session: service(),
    settings: service(),

    flowErrors: '',
    profileImage: null,

    signupDetails: alias('model'),

    actions: {
        validate(property) {
            return this.signupDetails.validate({property});
        },

        setImage(image) {
            this.set('profileImage', image);
        }
    },

    authenticate: task(function* (authStrategy, authentication) {
        try {
            let authResult = yield this.get('session')
                .authenticate(authStrategy, ...authentication);
            let promises = [];

            promises.pushObject(this.get('settings').fetch());
            promises.pushObject(this.get('config').fetchPrivate());

            // fetch settings and private config for synchronous access
            yield RSVP.all(promises);

            return authResult;
        } catch (error) {
            if (error && error.payload && error.payload.errors) {
                // we don't get back an ember-data/ember-ajax error object
                // back so we need to pass in a null status in order to
                // test against the payload
                if (isVersionMismatchError(null, error)) {
                    let versionMismatchError = new VersionMismatchError(error);
                    return this.get('notifications').showAPIError(versionMismatchError);
                }

                error.payload.errors.forEach((err) => {
                    err.message = err.message.htmlSafe();
                });

                this.set('flowErrors', error.payload.errors[0].message.string);

                if (error.payload.errors[0].message.string.match(/user with that email/)) {
                    this.get('signupDetails.errors').add('email', '');
                }

                if (error.payload.errors[0].message.string.match(/password is incorrect/)) {
                    this.get('signupDetails.errors').add('password', '');
                }
            } else {
                // Connection errors don't return proper status message, only req.body
                this.get('notifications').showAlert('There was a problem on the server.', {type: 'error', key: 'session.authenticate.failed'});
                throw error;
            }
        }
    }).drop(),

    signup: task(function* () {
        let setupProperties = ['name', 'email', 'password', 'token'];
        let notifications = this.get('notifications');

        this.set('flowErrors', '');
        this.get('signupDetails.hasValidated').addObjects(setupProperties);

        try {
            yield this.signupDetails.validate();
            yield this._completeInvitation();

            try {
                yield this._authenticateWithPassword();
                yield this.get('_sendImage').perform();
            } catch (error) {
                notifications.showAPIError(error, {key: 'signup.complete'});
            }
        } catch (error) {
            // ValidationEngine throws undefined
            if (!error) {
                this.set('flowErrors', 'Please fill out the form to complete your sign-up');
                return false;
            }

            if (error && error.payload && error.payload.errors && isEmberArray(error.payload.errors)) {
                if (isVersionMismatchError(error)) {
                    notifications.showAPIError(error);
                }
                this.set('flowErrors', error.payload.errors[0].message);
            } else {
                notifications.showAPIError(error, {key: 'signup.complete'});
            }
        }
    }).drop(),

    _completeInvitation() {
        let authUrl = this.get('ghostPaths.url').api('authentication', 'invitation');
        let signupDetails = this.get('signupDetails');

        return this.get('ajax').post(authUrl, {
            dataType: 'json',
            data: {
                invitation: [{
                    name: signupDetails.get('name'),
                    email: signupDetails.get('email'),
                    password: signupDetails.get('password'),
                    token: signupDetails.get('token')
                }]
            }
        });
    },

    _authenticateWithPassword() {
        let email = this.get('signupDetails.email');
        let password = this.get('signupDetails.password');

        return this.get('session')
            .authenticate('authenticator:cookie', email, password);
    },

    _sendImage: task(function* () {
        let formData = new FormData();
        let imageFile = this.get('profileImage');
        let uploadUrl = this.get('ghostPaths.url').api('uploads');

        if (imageFile) {
            formData.append('uploadimage', imageFile, imageFile.name);

            let user = yield this.get('session.user');
            let response = yield this.get('ajax').post(uploadUrl, {
                data: formData,
                processData: false,
                contentType: false,
                dataType: 'text'
            });

            let imageUrl = JSON.parse(response);
            let usersUrl = this.get('ghostPaths.url').api('users', user.id.toString());

            user.profile_image = imageUrl;

            return yield this.get('ajax').put(usersUrl, {
                data: {
                    users: [user]
                }
            });
        }
    })
});
