//Run when the document loads AND we have the config loaded.
(function() {
  "use strict";
  var config;
  Promise.all([
  new Promise(function(resolve, reject) {
    $.ajax('../config.json').done(function(data) {
      config = data;
      resolve();
    }).fail(function() {
      console.error("Failed to get config.");
      ga('send', 'event', 'error', 'config');
      reject();
    });
  }
  ),
  new Promise(function(resolve, reject) {
    var timeout = setTimeout(function() {
      console.error("Document never loaded? Something bad has happened!");
      reject();
    }, 10000);
    $(function() {
      clearTimeout(timeout);
      resolve();
    });
  }
  )
  ]).then(function() {

    var getParameterByName = function(name) {
      name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
      var regex = new RegExp("[\\?&]" + name + "=([^&#]*)");
      var results = regex.exec(location.search);
      return results === null  ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
    }

    //Overwrite config if present. Any failure will just cause this to be skipped.
    try {
      var configParam = JSON.parse(getParameterByName('config'));
      config = jQuery.extend(true, config, configParam);
    } catch (e) {
      console.warn("Failure in config overwrite, skipping.", e);
    }

    new Atmos(config);
  }, function() {
    console.error("Failed to initialize!");
    ga('send', 'event', 'error', 'init');
  });
})();

var Atmos = (function() {
  "use strict";

  var closeButton = '<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>';

  var guid = function() {
    var d = new Date().getTime();
    var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
      var r = (d + Math.random() * 16) % 16 | 0;
      d = Math.floor(d / 16);
      return (c == 'x' ? r : (r & 0x3 | 0x8)).toString(16);
    });
    return uuid;
  }

  /**
   * Atmos
   * @version 2.0

   * Configures an Atmos object. This manages the atmos interface.

   * @constructor
   * @param {string} catalog - NDN path
   * @param {Object} config - Object of configuration options for a Face.
   */
  var Atmos = function(config) {

    //Internal variables.
    this.results = [];
    this.resultCount = Infinity;
    this.name = null ;
    this.page = 0;
    this.resultsPerPage = 25;
    this.retrievedSegments = 0;

    //Config/init
    this.config = config;

    this.catalog = config['global']['catalogPrefix'];
    this.catalogPrefix = new Name(this.catalog);

    this.face = new Face(config['global']['faceConfig']);

    //Easy access dom variables
    this.categories = $('#side-menu');
    this.resultTable = $('#resultTable');
    this.filters = $('#filters');
    this.searchInput = $('#search');
    this.searchBar = $('#searchBar');
    this.searchButton = $('#searchButton');
    this.resultMenu = $('.resultMenu');
    this.alerts = $('#alerts');
    this.requestForm = $('#requestForm');

    var scope = this;

    $('.requestSelectedButton').click(function() {
      ga('send', 'event', 'button', 'click', 'request');
      scope.request(scope.resultTable.find('.resultSelector:checked:not([disabled])').parent().parent());
    });

    this.filterSetup();

    //Init autocomplete
    this.searchInput.autoComplete(function(field, callback) {
      ga('send', 'event', 'search', 'autocomplete');
      scope.autoComplete(field, function(data) {
        var list = data.next;
        var last = data.lastComponent === true;
        callback(list.map(function(element) {
          return field + element + (last ? "/" : "");
          //Don't add trailing slash for last component.
        }));
      });
    });

    //Handle search
    this.searchBar.submit(function(e) {
      ga('send', 'event', 'search', 'submit');
      e.preventDefault();
      if (scope.searchInput.val().length === 0) {
        if (!scope.searchBar.hasClass('has-error')) {
          scope.searchBar.addClass('has-error').append('<span class="help-block">Search path is required!</span>');
        }
        return;
      } else {
        scope.searchBar.removeClass('has-error').find('.help-block').fadeOut(function() {
          $(this).remove()
        });
      }
      scope.pathSearch();
    });

    this.searchButton.click(function() {
      console.log("Search Button Pressed");
      ga('send', 'event', 'button', 'click', 'search');
      scope.search();
    });

    //Result navigation handlers
    this.resultMenu.find('.next').click(function() {
      ga('send', 'event', 'button', 'click', 'next');
      if (!$(this).hasClass('disabled')) {
        scope.getResults(scope.page + 1);
      }
    });
    this.resultMenu.find('.previous').click(function() {
      ga('send', 'event', 'button', 'click', 'previous');
      if (!$(this).hasClass('disabled')) {
        scope.getResults(scope.page - 1);
      }
    });
    this.resultMenu.find('.clearResults').click(function() {
      ga('send', 'event', 'button', 'click', 'resultClear');
      scope.clearResults();
      $('#results').fadeOut(function() {
        $(this).addClass('hidden');
      });
    });

    //Change the number of results per page handler
    var rpps = $('.resultsPerPageSelector').click(function() {

      var t = $(this);

      if (t.hasClass('active')) {
        return;
      }

      rpps.find('.active').removeClass('active');
      t.addClass('active');
      scope.resultsPerPage = Number(t.text());
      scope.getResults(0);
      //Force return to page 1;

    });

    //Init tree search
    $('#treeSearch div').treeExplorer(function(path, callback) {
      console.log("Tree Explorer request", path);
      ga('send', 'event', 'tree', 'request');
      scope.autoComplete(path, function(data) {
        var list = data.next;
        var last = (data.lastComponent === true);

        if (last) {
          console.log("Redirecting last element request to a search.");
          scope.clearResults();
          scope.query(scope.catalog, {
            '??': path
          },
          function(interest, data) {
            console.log("Search response", interest, data);
            scope.name = interest.getName();
            scope.getResults(0);
          }, function(interest) {
            console.warn("Failed to retrieve final component.", interest, path);
            scope.createAlert("Failed to request final component. " + path + " See console for details.");
          });
          return;
          //Don't call the callback
        }

        console.log("Autocomplete response", list);
        callback(list.map(function(element) {
          return (path == "/" ? "/" : "") + element + "/";
        }));
      });
    });

    $('#treeSearch').on('click', '.treeSearch', function() {
      var t = $(this);

      scope.clearResults();

      var path = t.parent().parent().attr('id');

      console.log("Tree search:", path);

      scope.query(scope.catalog, {
        '??': path
      },
      function(interest, data) {
        //Success
        console.log("Tree search response", interest, data);

        scope.name = interest.getName();

        scope.getResults(0);
      },
      function(interest) {
        //Failure
        console.warn("Request failed! Timeout", interest);
        scope.createAlert("Request timed out.\"" + interest.getName().toUri() + "\" See console for details.");
      });

    });

    this.setupRequestForm();

    this.resultTable.popover({
      selector: ".metaDataLink",
      content: function() {
        return scope.getMetaData(this);
      },
      title: "Metadata",
      html: true,
      trigger: 'click',
      placement: 'bottom'
    });

    this.resultTable.on('click', '.metaDataLink', function(e) {
      //This prevents the page from scrolling when you click on a name.
      e.preventDefault();
    });

    this.resultTable.on('click', '.subsetButton', function() {
      var metaData = $(this).siblings('pre').text();
      var exp = /netcdf ([\w-]+)/;
      var match = exp.exec(metaData);
      var filename = match[0].replace(/netcdf /, '') + '.nc';
      scope.request(null , filename);
    });

  }

  Atmos.prototype.clearResults = function() {
    this.results = [];
    //Drop any old results.
    this.retrievedSegments = 0;
    this.resultCount = Infinity;
    this.page = 0;
    this.resultTable.empty();
  }

  Atmos.prototype.pathSearch = function() {
    var value = this.searchInput.val();

    this.clearResults();

    var scope = this;

    this.query(this.catalog, {
      "??": value
    },
    function(interest, data) {
      console.log("Query response:", interest, data);

      scope.name = interest.getName();

      scope.getResults(0);

    },
    function(interest) {
      console.warn("Request failed! Timeout", interest);
      scope.createAlert("Request timed out. \"" + interest.getName().toUri() + "\" See console for details.");
    });

  }

  Atmos.prototype.search = function() {

    var filters = this.getFilters();

    console.log("Search started!", this.searchInput.val(), filters);

    console.log("Initiating query");

    this.clearResults();

    var scope = this;

    this.query(this.catalog, filters,
    function(interest, data) {
      //Response function
      console.log("Query Response:", interest, data);

      scope.name = interest.getName();

      scope.getResults(0);

    }, function(interest) {
      //Timeout function
      console.warn("Request failed after 3 attempts!", interest);
      scope.createAlert("Request failed after 3 attempts. \"" + interest.getName().toUri() + "\" See console for details.");
    });

  }

  Atmos.prototype.autoComplete = function(field, callback) {

    var scope = this;

    var result = {};

    const getAll = function(interest, data) {

      if (data.getContent().length !== 0) {
        var resp = JSON.parse(data.getContent().toString().replace(/[\n\0]/g, ""));
        if (result.next) {
          result.next = result.next.concat(resp.next);
        } else {
          result = resp;
        }
      } else {
        callback(result);
      }

      var name = data.getName();
      var segment = name.components[name.getComponentCount() - 1];
      if (segment.toSegment() !== data.getMetaInfo().getFinalBlockId().toSegment()){
        name = name.getPrefix(-1); //Remove segment
        name.appendSegment(segment.toSegment() + 1);
        scope.expressInterest(name, getAll, function() {
          console.warn("Autocomplete timed out, results may be incomplete.");
          callback(result);
          //Return if we get a timeout.
        });
      } else {
        callback(result);
      }

    }

    this.query(this.catalog, {
      "?": field
    }, getAll);

  }

  Atmos.prototype.showResults = function(resultIndex) {

    var results = this.results.slice(this.resultsPerPage * resultIndex, this.resultsPerPage * (resultIndex + 1));

    var resultDOM = $(
    results.reduce(function(prev, current) {
      prev.push('<tr><td><input class="resultSelector" type="checkbox"></td><td class="popover-container"><a href="#" class="metaDataLink">');
      prev.push(current);
      prev.push('</a></td></tr>');
      return prev;
    }, ['<tr><th><input id="resultSelectAll" type="checkbox" title="Select All"> Select</th><th>Name</th></tr>']).join('')
    );

    resultDOM.find('#resultSelectAll').click(function() {
      if ($(this).is(':checked')) {
        resultDOM.find('.resultSelector:not([disabled])').prop('checked', true);
      } else {
        resultDOM.find('.resultSelector:not([disabled])').prop('checked', false);
      }
    });

    this.resultTable.hide().empty().append(resultDOM).slideDown('slow');

    this.resultMenu.find('.pageNumber').text(resultIndex + 1);
    this.resultMenu.find('.pageLength').text(this.resultsPerPage * resultIndex + results.length);

    if (this.resultsPerPage * (resultIndex + 1) >= this.resultCount) {
      this.resultMenu.find('.next').addClass('disabled');
    } else if (resultIndex === 0) {
      this.resultMenu.find('.next').removeClass('disabled');
    }

    if (resultIndex === 0) {
      this.resultMenu.find('.previous').addClass('disabled');
    } else if (resultIndex === 1) {
      this.resultMenu.find('.previous').removeClass('disabled');
    }

    $.scrollTo("#results", 500, {
      interrupt: true
    });

  }

  Atmos.prototype.getResults = function(index) {
    var scope = this;

    if ($('#results').hasClass('hidden')) {
      $('#results').removeClass('hidden').slideDown();
    }

    if ((scope.results.length === scope.resultCount) || (scope.resultsPerPage * (index + 1) < scope.results.length)) {
      //console.log("We already have index", index);
      scope.page = index;
      scope.showResults(index);
      return;
    }

    if (scope.name === null ) {
      console.error("This shouldn't be reached! We are getting results before a search has occured!");
      throw new Error("Illegal State");
    }

    var interestName = new Name(scope.name);

    // Interest name should be /<catalog-prefix>/query/<query-param>/<version>/<#seq>
    if (scope.name.size() === (scope.catalogPrefix.size() + 3)) {
      interestName = interestName.appendSegment(scope.retrievedSegments++);
      //console.log("Requesting data index: (", scope.retrievedSegments - 1, ") at ", interestName.toUri());
    }

    this.expressInterest(interestName,
    function(interest, data) {
      //Response

      if (data.getContent().length === 0) {
        scope.resultMenu.find('.totalResults').text(0);
        scope.resultMenu.find('.pageNumber').text(0);
        scope.resultMenu.find('.pageLength').text(0);
        console.log("Empty response.");
        scope.resultTable.html("<tr><td>Empty response. This usually means no results.</td></tr>");
        return;
      }

      var content = JSON.parse(data.getContent().toString().replace(/[\n\0]/g, ""));

      if (!content.results) {
        scope.resultMenu.find('.totalResults').text(0);
        scope.resultMenu.find('.pageNumber').text(0);
        scope.resultMenu.find('.pageLength').text(0);
        console.log("No results were found!");
        scope.resultTable.html("<tr><td>No Results</td></tr>");
        return;
      }

      scope.results = scope.results.concat(content.results);

      scope.resultCount = content.resultCount;

      scope.resultMenu.find('.totalResults').text(scope.resultCount);

      scope.page = index;

      // reset scope.name
      scope.name = new Name(data.getName().getPrefix(scope.catalogPrefix.size() + 3));

      scope.getResults(index);
      //Keep calling this until we have enough data.

    }, function() {}//Ignore failure
    );

  }

  Atmos.prototype.query = function(prefix, parameters, callback, timeout) {

    var queryPrefix = new Name(prefix);
    queryPrefix.append("query");

    var jsonString = JSON.stringify(parameters);
    queryPrefix.append(jsonString);

    this.expressInterest(queryPrefix, callback, timeout);

  }


  Atmos.prototype.expressInterest = function(name, success, failure) {

    var interest = new Interest(name);
    interest.setInterestLifetimeMilliseconds(1500);
    interest.setMustBeFresh(true);

    const face = this.face;

    async.retry(4, function(done) {
      face.expressInterest(interest, function(interest, data) {
        done();
        success(interest, data);
      }, function(interest) {
        done("Interest timed out 4 times.", interest);
      });
    }, function(err, interest) {
      if (err) {
        console.log(err, interest);
        failure(interest);
      }
    });

  }

  /**
   * This function returns a map of all the categories active filters.
   * @return {Object<string, string>}
   */
  Atmos.prototype.getFilters = function() {
    var filters = this.filters.children().toArray().reduce(function(prev, current) {
      var data = $(current).text().split(/:/);
      prev[data[0]] = data[1];
      return prev;
    }, {});
    //Collect a map<category, filter>.
    //TODO Make the return value map<category, Array<filter>>
    return filters;
  }

  /**
   * Creates a closable alert for the user.

   * @param {string} message
   * @param {string} type - Override the alert type.
   */
  Atmos.prototype.createAlert = function(message, type) {

    var alert = $('<div class="alert"><div>');
    alert.addClass(type ? type : 'alert-info');
    alert.text(message);
    alert.append(closeButton);

    this.alerts.append(alert);
  }

  /**
   * Requests all of the names represented by the buttons in the elements list.

   * @param elements {Array<jQuery>} A list of the table row elements
   * @param subsetFileName {String} If present then do a subsetting request instead.
   */
  Atmos.prototype.request = function() {

    //Pseudo globals.
    var keyChain;
    var certificateName;
    var keyAdded = false;

    return function(elements, subsetFilename) {

      var names = [];
      $(elements).find('.metaDataLink').each(function() {
        var name = $(this).text();
        names.push(name);
      });

      var subset = false;

      if (!subsetFilename) {
        $('#subsetting').hide();
      } else {
        $('#subsetting').show();
        subset = true;
      }

      var scope = this;
      this.requestForm.on('submit', function(e) {
        //This will be registered for the next submit from the form.
        e.preventDefault();

        $('#request .alert').remove();

        var variables = [];
        if (subset) {
          $('#subsetVariables .row').each(function() {
            var t = $(this);
            var values = {};
            t.find('.values input').each(function() {
              var t = $(this);
              values[t.attr('name')] = t.val();
            });
            variables.push({
              variable: t.find('.variable').val(),
              values: values
            });
          });
        }

        //Form checking
        var dest = scope.requestForm.find('#requestDest .active');
        if (dest.length !== 1) {
          var alert = $('<div class="alert alert-warning">A destination is required!' + closeButton + '<div>');
          $('#request > .panel-body').append(alert);
          return;
        }

        $('#request').modal('hide');
        //Initial params are ok. We can close the form.

        scope.cleanRequestForm();

        $(this).off(e);
        //Don't fire this again, the request must be regenerated

        //Key setup
        if (!keyAdded) {
          if (!scope.config.retrieval.demoKey || !scope.config.retrieval.demoKey.pub || !scope.config.retrieval.demoKey.priv) {
            scope.createAlert("This host was not configured to handle retrieval! See console for details.", 'alert-danger');
            console.error("Missing/invalid key! This must be configured in the config on the server.", scope.config.demoKey);
            return;
          }

          //FIXME base64 may or may not exist in other browsers. Need a new polyfill.
          var pub = new Buffer(base64.toByteArray(scope.config.retrieval.demoKey.pub));
          //MUST be a Buffer (Buffer != Uint8Array)
          var priv = new Buffer(base64.toByteArray(scope.config.retrieval.demoKey.priv));

          var identityStorage = new MemoryIdentityStorage();
          var privateKeyStorage = new MemoryPrivateKeyStorage();
          keyChain = new KeyChain(new IdentityManager(identityStorage,privateKeyStorage),
          new SelfVerifyPolicyManager(identityStorage));

          var keyName = new Name("/retrieve/DSK-123");
          certificateName = keyName.getSubName(0, keyName.size() - 1)
          .append("KEY").append(keyName.get(-1))
          .append("ID-CERT").append("0");

          identityStorage.addKey(keyName, KeyType.RSA, new Blob(pub,false));
          privateKeyStorage.setKeyPairForKeyName(keyName, KeyType.RSA, pub, priv);

          scope.face.setCommandSigningInfo(keyChain, certificateName);

          keyAdded = true;

        }

        //Retrieval
        var retrievePrefix = new Name("/catalog/ui/" + guid());

        scope.face.registerPrefix(retrievePrefix,
        function(prefix, interest, face, interestFilterId, filter) {
          //On Interest
          //This function will exist until the page exits but will likely only be used once.

          var data = new Data(interest.getName());
          var content;
          if (subset) {
            content = JSON.stringify({
              name: subsetFilename,
              subset: variables
            });
          } else {
            content = JSON.stringify(names);
          }
          //Blob breaks the data! Don't use it
          data.setContent(content);
          //TODO Packetize this.
          keyChain.sign(data, certificateName);

          try {
            face.putData(data);
            console.log("Responded for", interest.getName().toUri(), data);
            scope.createAlert("Data retrieval has initiated.", "alert-success");
          } catch (e) {
            console.error("Failed to respond to", interest.getName().toUri(), data);
            scope.createAlert("Data retrieval failed.");
          }

        }, function(prefix) {
          //On fail
          scope.createAlert("Failed to register the retrieval URI! See console for details.", "alert-danger");
          console.error("Failed to register URI:", prefix.toUri(), prefix);
        }, function(prefix, registeredPrefixId) {
          //On success
          var name = new Name(dest.text());
          name.append(prefix);

          scope.expressInterest(name,
          function(interest, data) {
            //Success
            console.log("Request for", name.toUri(), "succeeded.", interest, data);
          },
          function() {
            console.warn("Failed to request from retrieve agent.");
          }
          );
        }
        );

      });
      $('#request').modal();
      //This forces the form to be the only option.

    }

  }();

  Atmos.prototype.filterSetup = function() {
    //Filter setup

    var prefix = new Name(this.catalog).append("filters-initialization");

    var scope = this;

    this.getAll(prefix, function(data) {
      //Success
      var raw = JSON.parse(data.replace(/[\n\0]/g, ''));
      //Remove null byte and parse

      console.log("Filter categories:", raw);

      $.each(raw, function(index, object) {
        //Unpack list of objects
        $.each(object, function(category, searchOptions) {
          //Unpack category from object (We don't know what it is called)
          //Create the category
          var e = $('<li><a href="#">' + category.replace(/_/g, " ") + '</a><ul class="subnav nav nav-pills nav-stacked"></ul></li>');

          var sub = e.find('ul.subnav');
          $.each(searchOptions, function(index, name) {
            //Create the filter list inside the category
            var item = $('<li><a href="#">' + name + '</a></li>');
            sub.append(item);
            item.click(function() {
              //Click on the side menu filters
              if (item.hasClass('active')) {
                //Does the filter already exist?
                item.removeClass('active');
                scope.filters.find(':contains(' + category + ':' + name + ')').remove();
              } else {
                //Add a filter
                item.addClass('active');
                var filter = $('<span class="label label-default"></span>');
                filter.text(category + ':' + name);

                scope.filters.append(filter);

                filter.click(function() {
                  //Click on a filter
                  filter.remove();
                  item.removeClass('active');
                });
              }

            });
          });

          //Toggle the menus. (Only respond when the immediate tab is clicked.)
          e.find('> a').click(function() {
            scope.categories.find('.subnav').slideUp();
            var t = $(this).siblings('.subnav');
            if (!t.is(':visible')) {
              //If the sub menu is not visible
              t.slideDown(function() {
                t.triggerHandler('focus');
              });
              //Make it visible and look at it.
            }
          });

          scope.categories.append(e);

        });
      });

    }, function(interest) {
      //Timeout
      scope.createAlert("Failed to initialize the filters!", "alert-danger");
      console.error("Failed to initialize filters!", interest);
      ga('send', 'event', 'error', 'filters');
    });

  }

  /**
   * This function retrieves all segments in order until it knows it has reached the last one.
   * It then returns the final joined result.

   * @param prefix {String|Name} The ndn name we are retrieving.
   * @param callback {function(String)} if successful, will call the callback with a string of data.
   * @param failure {function(Interest)} if unsuccessful, will call failure with the last failed interest.
   * @param stop {boolean} stop if no finalBlock.
   */
  Atmos.prototype.getAll = function(prefix, callback, failure, stop) {

    var scope = this;
    var d = [];

    var name = new Name(prefix);
    var segment = 0;

    var request = function() {

      var n2 = new Name(name);
      n2.appendSegment(segment);

      scope.expressInterest(n2, handleData, function() {});
      //Forward to handleData and ignore error
    }

    var handleData = function(interest, data) {

      d.push(data.getContent().toString());

      var hasFinalBlock = data.getMetaInfo().getFinalBlockId().value.length === 0;
      var finalBlockStop = hasFinalBlock && stop;

      if (finalBlockStop ||
      (!hasFinalBlock && interest.getName().get(-1).toSegment() == data.getMetaInfo().getFinalBlockId().toSegment())) {
        callback(d.join(""));
      } else {
        segment++;
        request();
      }

    }

    request();

  }

  Atmos.prototype.cleanRequestForm = function() {
    $('#requestDest').prev().removeClass('btn-success').addClass('btn-default');
    $('#requestDropText').text('Destination');
    $('#requestDest .active').removeClass('active');
    $('#subsetMenu').attr('class', 'collapse');
    $('#subsetVariables').empty();
    $('#request .alert').alert('close').remove();
  }

  Atmos.prototype.setupRequestForm = function() {

    var scope = this;

    this.requestForm.find('#requestCancel').click(function() {
      $('#request').unbind('submit')//Removes all event handlers.
      .modal('hide');
      //Hides the form.
      scope.cleanRequestForm();
    });

    var dests = $(this.config['retrieval']['destinations'].reduce(function(prev, current) {
      prev.push('<li><a href="#">');
      prev.push(current);
      prev.push("</a></li>");
      return prev;
    }, []).join(""));

    this.requestForm.find('#requestDest').append(dests)
    .on('click', 'a', function(e) {
      $('#requestDest .active').removeClass('active');
      var t = $(this);
      t.parent().addClass('active');
      $('#requestDropText').text(t.text());
      $('#requestDest').prev().removeClass('btn-default').addClass('btn-success');
    });

    var addVariable = function(selector) {
      var ele = $(selector).clone().attr('id', '');
      ele.find('.close').click(function() {
        ele.remove();
      });
      $('#subsetVariables').append(ele);
    }

    $('#subsetAddVariableBtn').click(function() {
      addVariable('#customTemplate');
    });
    $('#subsetAddTimeVariable').click(function() {
      addVariable('#timeTemplate');
    });
    $('#subsetAddLocVariable').click(function() {
      addVariable('#locationTemplate');
    });

  }

  Atmos.prototype.getMetaData = (function() {

    var cache = {};

    return function(element) {
      var name = $(element).text();

      ga('send', 'event', 'request', 'metaData');

      var subsetButton = '<button class="btn btn-default subsetButton" type="button">Subset</button>';

      if (cache[name]) {
        return [subsetButton, '<pre class="metaData">', cache[name], '</pre>'].join('');
      }

      var prefix = new Name(name).append("metadata");
      var id = guid();
      //We need an id because the return MUST be a string.
      var ret = '<div id="' + id + '"><span class="fa fa-spinner fa-spin"></span></div>';

      this.getAll(prefix, function(data) {
        var el = $('<pre class="metaData"></pre>');
        el.text(data);
        var container = $('<div></div>');
        container.append($(subsetButton));
        container.append(el);
        $('#' + id).empty().append(container);
        cache[name] = data;
      }, function(interest) {
        $('#' + id).text("The metadata is unavailable for this name.");
        console.log("Data is unavailable for " + name);
      });

      return ret;

    }
  })();

  return Atmos;

})();
