function FieldsetHelper(sessionId) {
    var self = this;
    self.objectIds = {};
    self.fieldsetIds = {};
    self.fieldsetsByName = {};
    var promise;
    self.refreshFieldSetList = function() {
        var conn = new jsforce.Connection({ accessToken: sessionId });
            promise = conn.metadata.list([{type: "CustomObject"}, {type: "FieldSet"}], "37.0")
                .then(function(res) {
                    for (var i = 0; i < res.length; i++) {
                        if (res[i].type === "CustomObject") {
                            var id = res[i].id;
                            if (id !== undefined && id.length > 0) {
                                id = id.substring(0, 15);
                            } else {
                                id = res[i].fullName;
                            }
                            self.objectIds[res[i].fullName] = id;
                        } else {
                            self.fieldsetIds[res[i].fullName] = res[i].id.substring(0, 15);
                        }
                    }

                    // build a map of fieldset names to lists of object name, object id, fieldset id
                    for (var fs in self.fieldsetIds) {
                        if (!self.fieldsetIds.hasOwnProperty(fs)) { continue; }
                        var split = fs.split(".");
                        var objectName = split[0];
                        var fieldsetName = split[1].toUpperCase();
                        var list = self.fieldsetsByName[fieldsetName];
                        if (!list) {
                            list = [];
                            self.fieldsetsByName[fieldsetName] = list;
                        }
                        var fieldsetId = self.fieldsetIds[fs];
                        var objectId = self.objectIds[objectName];
                        list.push({ name: objectName, id: objectId, fs: fieldsetId });
                    }
                }, function(err) {
                     console.error(err);
                }).catch(function(err) {
                      console.error(err);
                });
    }
    self.refreshFieldSetList();

    self.enhance = function() {
        promise.then(function() {
            $(".fieldset-link").each(function () {
                var elem = $(this);
                elem.children("span").wrap(function() {
                    var childSpan = $(this);
                    var possibleFieldsets = self.fieldsetsByName[childSpan.text().toUpperCase()];
                    if (possibleFieldsets === undefined) {
                        return;
                    }

                    var href;
                    if (possibleFieldsets && possibleFieldsets.length === 1) {
                        // only a single field set has this name, so we know which one it is
                        var fs = possibleFieldsets[0];
                        href = "/setup/FieldSetEditor.apexp?tableEnumOrId=" + fs.id + "&id=" + fs.fs;
                    } else {
                        // multiple field sets with this name, pass all the object and field set ids to
                        // the redirector page and have it check the card to determine which to use
                        var cardName = elem.siblings(".card-name").text();
                        href = "/apex/EditFieldSetRedirector?name=" + cardName;
                        for (var i = 0; i < possibleFieldsets.length; i++) {
                            var fs = possibleFieldsets[i];
                            href += "&" + fs.name + "=" + fs.id + "&" + fs.name + "fs=" + fs.fs;
                        }
                    }
                    href += '&retURL=' + encodeURIComponent(window.location.href);
                    return $("<a>").attr("href", href);
                });
            });

            $(".fieldset-field").each(function() {
                var elem = $(this);
                var objectName = $(".sobject-field").val();
                var objectId = self.objectIds[objectName];

                var addLink = $("<a><span title=\"Add\" class=\"inline-icon fa fa-plus\"></span></a>")
                    .attr("target", "_blank");

                if (objectId !== undefined) {
                    addLink.attr("href", "/0IX/e?tableEnumOrId=" + objectId);
                }

                var editLink = $("<a><span title=\"Edit\" class=\"inline-icon fa fa-pencil\"></span></a>")
                    .attr("target", "_blank");
                editLink.click(function() {
                    var fieldsetName = $(".fieldset-field").val();
                    if (fieldsetName !== undefined && fieldsetName.length > 0) {
                        var fieldsetId = self.fieldsetIds[objectName + "." + fieldsetName];
                        editLink.attr("href", "/setup/FieldSetEditor.apexp?tableEnumOrId=" + objectId + "&id=" + fieldsetId);
                    } else {
                        editLink.attr("href", "");
                        return false;
                    }
                });

                $(".sobject-field").change(function() {
                    addLink.children().first().toggleClass('inline-icon-disabled', !$.trim($(this).val()));
                });

                if (!$.trim($(".sobject-field").val())) {
                    addLink.children().first().addClass('inline-icon-disabled');
                }

                elem.change(function() {
                    editLink.children().first().toggleClass('inline-icon-disabled', !$.trim($(this).val()));
                });

                if (!$.trim(elem.val())) {
                    editLink.children().first().addClass('inline-icon-disabled');
                }

                elem.parent().append(addLink, editLink);
            });
        }).catch(function(err) {
            console.error(err);
        });
    };
}