define([
    'app'
  , 'text!details.html!strip'
  , 'css!details'
  ],
  function (App, source) {
    var that = {};
    var priv = {};

    // cleanup memory
    priv.cleanupMemory = function (memory) {
      var item, created,
        oldest = 0,
        limit = App.settings.max_items_in_ram || 15,
        size = App.util.objectSize(memory);

      if (size > limit) {
        // find oldest
        for (item in memory) {
          if (memory.hasOwnProperty(item)) {
            created = memory[item][1];
            if (oldest < created) {
              oldest = created;
            }
          }
        }
        // purge
        for (item in memory) {
          if (memory.hasOwnProperty(item)) {
            if (created === memory[item][1]) {
              delete memory[item];
            }
          }
        }
      }
    };

    // retrieve and store item to display
    priv.storeItem = function (params) {
      var id, now, spec, module;

      // we will have an item to display. Grab it and go!
      if (location.search !== "") {
        spec = {};

        spec.pointer = location.search.split("=")[1];
        spec.storage = "items"
        spec.method = "get"
        spec.doc = {"_id": spec.pointer }

        // TODO: should be passed via JSON?
        module = "storage";
        now = new Date().getTime();
      } else {
        // route to all products
        $.mobile.changePage("products.html", {"transition":"fade"});
      }

      // jio response
      spec.callback = function(err, response) {

        if (err) {
          // error handling
        } else {
          id = response._id;

          App.cacheItems[id] = [response, now];
          App.activeItem = id;

          // memory
          priv.cleanupMemory(App.cacheItems);
        }

        // this is not response.callback(!!)
        params.callback_mockup(params.source);
      }
      // query for items
      App[module].switchboard(spec);
    };

    // response object
    that.data = source;
    that.before = function (source, callback_mockup) {
      var spec = {};

      spec.gadget = RenderJs.getSelfGadget();
      // TODO: this is for page event bindings. Once JQM content replaces
      // page, remove this and make the gadget the content section to
      // be updated.
      spec.page = App.util.closest(spec.gadget.dom.get(0), "div[data-role='page']");
      spec.pageId = "#" + spec.page.id;
      spec.source = source;
      spec.callback_mockup = callback_mockup;

      if (!spec.page.getAttribute("events_details")) {
        spec.page.setAttribute("events_details", true);
        $(document).on("pagebeforeshow.details", spec.pageId, function (e, data) {
          // TODO: if we allow to reload, we also need to trigger refresh on
          // so we need to reload this every time a page is shown. question
          // is how to trigger a refresh on this element ONLY
          priv.storeItem(spec);
        });
        // and run intial
        priv.storeItem(spec);
      }
    };

    that.after = function (self) {
      if (App === undefined) {
        def = new $.Deferred;

        def.done(function(gadget) {
          // prefix instance-ids, pass JSON
          App.renderGadgets(gadget);
        });

        window.fallbackLoader.deferreds.push(def);
        window.fallbackLoader.args.push(self);
      } else {
        // prefix instance-ids, pass JSON
        App.renderGadgets(self);
      }
    };

  // return response object
  return that;
  }
);
