import _ from 'lodash';
import { Promise } from 'rsvp';
import Immutable from 'immutable';
import { ActionTypes } from 'constants/Common';
import dispatcher from 'dispatcher';
import { i18n } from 'lib/i18n';
import getErrors from 'lib/getErrors';
import toBlob from 'lib/toBlob';
import orgApi from 'api/org';
import orgProfileApi from 'api/org.profile';
import servicesApi from 'api/services';

export default {
    updateInfo,
    remove,
    setLogo,
    removeLogo,
    fetchLogo,
    changeOwner,
    getOwnerChangeStatus,
    checkOwnerChangeStatus,
};

const MAX_LOGO_IMAGE_FILE_SIZE = 7 * 1024 * 1024;

function pushError(error) {
    return Promise.resolve().then(() => ({
        errors: Immutable.fromJS({ _common: error }),
    }));
}

function updateInfo(data) {
    return orgProfileApi.update(data).then(response => {
        const errors = getErrors(response);

        if (!errors.isEmpty()) {
            return { errors };
        }

        const orgId = _.get(response, 'state.organization');

        dispatcher.dispatch(ActionTypes.RECEIVE_ORGANIZATION, response.organizations[orgId]);
    });
}

function remove(data) {
    return orgApi.remove(data).then(response => {
        const errors = getErrors(response);

        if (!errors.isEmpty()) {
            return { errors };
        }

        dispatcher.dispatch(ActionTypes.RECEIVE_MIXED_DATA, response);
    });
}

function setLogo(data) {
    if (!data.logo_file) {
        return pushError(i18n('logo.error.no_file'));
    }

    const blob = toBlob(data.logo_file);

    if (blob.size > MAX_LOGO_IMAGE_FILE_SIZE) {
        return pushError(i18n('logo.error.file_too_large'));
    }

    const formData = new FormData();

    formData.append('logo_file', blob);
    data = formData;

    dispatcher.dispatch(ActionTypes.START_PROCESS);

    return orgProfileApi.setLogo(data).then(response => {
        const errors = getErrors(response);

        if (!errors.isEmpty()) {
            return { errors };
        }

        dispatcher.dispatch(ActionTypes.RECEIVE_MIXED_DATA, {
            settings: {},
        });
        dispatcher.dispatch(ActionTypes.END_PROCESS);
    });
}

function removeLogo() {
    dispatcher.dispatch(ActionTypes.START_PROCESS);

    return orgProfileApi.removeLogo().then(response => {
        const errors = getErrors(response);

        if (!errors.isEmpty()) {
            return { errors };
        }

        dispatcher.dispatch(ActionTypes.RECEIVE_MIXED_DATA, {
            settings: {},
        });
        dispatcher.dispatch(ActionTypes.END_PROCESS);
    });
}

function fetchLogo() {
    dispatcher.dispatch(ActionTypes.START_PROCESS);

    return Promise.all([
        orgProfileApi.read(),
        servicesApi.readMenu(),
    ]).then(responses => {
        dispatcher.dispatch(ActionTypes.RECEIVE_MIXED_DATA, {
            organizations: _.get(responses[0], 'organizations'),
            settings: _.get(responses[1], 'settings'),
        });
        dispatcher.dispatch(ActionTypes.END_PROCESS);
    });
}

function receiveOwnerChangeStatus(response) {
    const errors = getErrors(response);

    if (!errors.isEmpty()) {
        return { errors };
    }

    dispatcher.dispatch(ActionTypes.RECEIVE_MIXED_DATA, _.pick(response, 'owner_change'));
    dispatcher.dispatch(ActionTypes.END_PROCESS);

    return response && response.owner_change;
}

function changeOwner(data) {
    dispatcher.dispatch(ActionTypes.START_PROCESS);

    return orgApi.changeOwner(data).then(receiveOwnerChangeStatus)
        .catch(e => {
            dispatcher.dispatch(ActionTypes.END_PROCESS);
            throw e;
        });
}

function getOwnerChangeStatus(data) {
    return orgApi.getOwnerChangeStatus(data).then(receiveOwnerChangeStatus)
        .catch(e => {
            dispatcher.dispatch(ActionTypes.END_PROCESS);
            throw e;
        });
}

const TASK_PROGRESS_STATUSES = ['free', 'in-progress'];
const FINAL_TASK_STATUSES = ['success', 'failed'];
const TASK_POLLING_TIMEOUT = 5000;

let currentOwnerChangeStatusCheck;

// polling
function checkOwnerChangeStatus(data) {
    if (!currentOwnerChangeStatusCheck) {
        currentOwnerChangeStatusCheck = new Promise((resolve, reject) => {
            const check = () => {
                getOwnerChangeStatus(data)
                    .then(({ status }) => {
                        if (FINAL_TASK_STATUSES.indexOf(status) !== -1) {
                            resolve(status);
                        } else if (TASK_PROGRESS_STATUSES.indexOf(status) !== -1) {
                            setTimeout(check, TASK_POLLING_TIMEOUT);
                        } else {
                            reject();
                        }
                    })
                    .catch(reject);
            };

            check();
        });
    }

    return currentOwnerChangeStatusCheck;
}
