function MultiCredentialService (Rest, ProcessErrors, $q, GetBasePath)  {

    const handleError = (method, resource, permitted = []) => {
        return ({ data, status }) => {
            if (permitted.indexOf(status) > -1) {
                return { data, status };
            }
            const hdr = 'Error!';
            const msg = `${resource} request failed. ${method} returned status: ${status}`;
            return ProcessErrors(null, data, status, null, { hdr, msg });
        };
    };

    const associate = ({ related }, id) => {
        Rest.setUrl(related.credentials);
        return Rest
            .post({ id })
            .then(({ data }) => data.results)
            .catch(handleError('POST', 'credential association'));
    };

    const disassociate = ({ related }, id) => {
        Rest.setUrl(related.credentials);
        return Rest
            .post({ id, disassociate: true })
            .catch(handleError('POST', 'credential disassociation'));
    };

    this.saveRelated = ({ related }, credentials) => {
        Rest.setUrl(related.credentials);
        return Rest
            .get()
            .then(({ data }) => {
                const currentlyAssociated = data.results.map(c => c.id);
                const selected = credentials.map(c => c.id);

                const disassociationPromises = currentlyAssociated
                    .filter(id => selected.indexOf(id) < 0)
                    .map(id => disassociate({ related }, id));

                const associationPromises = selected
                    .filter(id => currentlyAssociated.indexOf(id) < 0)
                    .map(id => associate({ related }, id));

                const promises = disassociationPromises
                    .concat(associationPromises);

                return $q.all(promises);
            });
    };

    this.getRelated = ({ related }, params = { permitted: [] }) => {
        Rest.setUrl(related.credentials);
        return Rest
            .get()
            .catch(handleError('GET', 'related credentials', params.permitted));
    };

    this.getCredentials = () => {
        Rest.setUrl(GetBasePath('credentials'));
        return Rest
            .get()
            .catch(handleError('GET', 'related credentials'));
    };

    this.getCredentialTypes = () => {
        Rest.setUrl(GetBasePath('credential_types'));
        return Rest
            .get({ params: { page_size: 200 }})
            .catch(handleError('GET', 'credential types'));
    };

    this.isReadOnly = credential => {
        const canEdit = _.get(credential, 'summary_fields.user_capabilities.edit');
        const canDelete = _.get(credential, 'summary_fields.user_capabilities.delete');

        return !(canEdit || canDelete);
    };

    this.createTag = (credential, credential_types) => {
        const credentialTypeId = credential.credential_type || credential.credential_type_id;
        const credentialType = credential_types.find(t => t.id === credentialTypeId);

        return {
            id: credential.id,
            name: credential.name,
            kind: _.get(credentialType, 'kind'),
            typeName: _.get(credentialType, 'name'),
            info: _.get(credential, 'inputs.vault_id'),
            readOnly: this.isReadOnly(credential),
        };
    };
}

MultiCredentialService.$inject = [
    'Rest',
    'ProcessErrors',
    '$q',
    'GetBasePath',
];

export default MultiCredentialService;
