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

    // in the perfect renderjs world, the items gadget should either expose
    // an API on how to pass ... query string ... or have default config
    // like pointers or a default fallback. This is what we are doing currently.
    // Leave it like that!

    // generate items to display
    priv.generateItems = function (params) {
      var markup, spec,
        id = params.gadget.dom.attr('id').split("__").splice(-1)[0],
        config = params.gadget.state[0][id]._config,
        module = config.datasource.module,

        // settable options
        screen = App.settings.screen_format,
        size = screen === "small" ? "small" : "medium",
        shortcut = size.substring(0, 1),
        identifier = App.settings.identifier || "item_id";

        spec = {};

        spec.pointer = config.datasource.pointer;
        spec.method = spec.pointer ? undefined : config.datasource.method || "allDocs";
        spec.storage = spec.pointer ? undefined : config.datasource.storage || "items";
        spec.options = spec.pointer ? undefined : {
          "limit": config.datasource.limit || [0, 24],
          "sort_on": config.datasource.sort || [["_id", "descending"]],
          "select_list": config.datasource.fields || undefined
        };

        // if we have a search tag being passed, run a search
        if (location.search !== "") {
          spec.query = true;
          spec.query_string = location.search.split("=")[1].replace("+", " ");
        }

        spec.callback = function(err, response) {
          var item, i, str = "", price;

        // cleanup

        // no results
        // TODO: show something for users like most-searched/sold...
        // TODO: this is optionable
        if (response.total_rows === 0) {

          str += "<li data-icon='false' class='empty_results'>" +
            "<h3 class='translate' data-i18n='items.results_zero'></h3>" +
            "<p class='translate' data-i18n='items.results_modify'></p>" +
            "</li>";

        } else {
          // generate results
          for (i = 0; i < response.total_rows; i += 1) {
            item = response.rows[i].value;

            if (item.price === item.original_price) {
              price = item.price + "€";
            } else {
              price = "<span class='rebate'>" + item.price + "€</span> (" +
                item.original_price + "€)";
            }

            str += "<li data-icon='false'>" +
              "<a href='details.html?"+ identifier + "=" +
              encodeURI(item[identifier]) +
              "' title='" + item.brand + ", " + item.title + "'>" +
              "<span class='img_container_items'>" +
              "<img alt='" + item.title + "' src='" +
              item.media + item.dimensions[0].vars[0].media.img[0][shortcut] +
              size + "' /></span><span class='description_items'>" +
              item.brand + " " + item.title + " " + price + "</span></a></li>";
          }
        }

        // add to data
        // TODO: this should only replace list items and not the whole
        // gadget content...
        markup = params.source.replace(/<!-- items -->/g, str);

        // this is not response.callback(!!)
        params.callback_mockup(markup);
      }

      // query for items
      App[module].switchboard(spec);
    };

    // response object
    that.data = source;
    that.mockup = 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_items")) {
        spec.page.setAttribute("events_items", true);
        $(document).on("pagebeforeshow.items", 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
          // > the gadgets should tell whether they need enhancement!
          //if ($.mobile.firstPage.attr('id') !== spec.pageId.replace("#","")) {
            priv.generateItems(spec);
          //}
        });
        // and run intial
        priv.generateItems(spec);
      }
    };

    that.callback = function (self) {
      // set binding for opening a detailed view
      // TODO: this should also be a link-method call
      self.dom.find("ul").on("click", "a", function (e) {
        var target, search = {};

        e.preventDefault();
        target = App.util.closest(e.target, "a").getAttribute("href").split("?")[1].split("=");
        search[target[0]] = target[1];

        // show this item
        $.mobile.changePage("details.html", {
          "transition": "slide",
          "data": search
        });
      });

      if (App === undefined) {
        def = new $.Deferred;

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

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

  // return response object
  return that;
  }
);
