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

    response.data = source;
    response.callback = function (self) {

      var that = {};
      var priv = {};
      var def;

      // ====================================================================
      //                            ATTRIBUTES
      // ====================================================================

      // this gadget
      priv.gadget = self;

      // document
      priv.doc = $.mobile.document;

      // ====================================================================
      //                            INTERNAL METHODS
      // ====================================================================

      //
      // prefix element id with the parent id to allow instantiation
      // @method prefixId
      // @param  {string} id > of current gadget/element
      // @param  {object} parent gadget
      // @return {string} new id for gadget/element
      //
      priv.prefixId = function (id, gadget) {
        return gadget.dom.attr('id') + "__" + id;
      }

      //
      // modify the icon of the popup button
      // @method setIcon
      // @param {object} gadget > gadget object
      // @param {string} icon > class name for icon
      //
      priv.setIcon = function (gadget, language) {
        // TODO: remove setTimeout!
        window.setTimeout(function(){
          $(".pick_language")
            .removeClass("[class|='ui-icon']")
            .addClass("ui-icon-" + language);
        },50);
      };

      //
      // translate all page elements labelled with class "translate"
      // @method translate
      // @param {string} language > language to set
      //
      priv.translate = function (language, target) {
        var collection = target || $('body');
        collection.find("." + App.settings.language_selector).i18n();
      };

      //
      // setup i18n plugin
      // @method setupTranslations
      // @param {string} language > default language to set
      //
      priv.setTranslations = function (language) {
        if (App.settings.language_set === "false") {
          $.i18n.init({
            "lng": language,
            "load": 'current',
            "detectLngQS": 'lang',
            "fallbackLng": false,
            "resGetPath": 'lang/__lng__/__ns__.json',
            "ns": 'app'
          }, function () {
            priv.translate(language);
          });
          App.settings.language_set = "true";
        } else {
          priv.translate(language);
        }
      };

      //
      // initialize i18n translation plugin
      // @method initialize
      // @param {string} language > language to set
      //
      priv.initialize = function (language) {
        // setup i18n
        priv.setTranslations(language);

        // setup icon
        priv.setIcon(language);
      };

      // ========================================================================
      //                            BINDINGS
      // ========================================================================
      // TODO: remove once callable per link!
      // TODO: why do I need to call $.i18n.setLng again?
      priv.doc.on("ready", function () {
        var that = $(this);

        that
          .filter(function() {
            return that.attr("i18n") !== "set";
          })
          .attr("i18n", "set")
          .on("click", "a.change_language", function (e) {
            var language = this.getAttribute("href").replace('?lang=','');
            e.preventDefault();
            e.stopPropagation();

            $(".popup_all").popup( 'close' );

            if (App.settings.language_current !== language) {
              // update language
              App.settings.language_current = language;

              // update icon
              priv.setIcon(language);

              // translate
              $.i18n.setLng(language, function() {
                priv.setTranslations(language);
              });
            }
          });
      });

      priv.deferred_setup_translations = function (gadget) {
      // ====================================================================
      //                            PUBLISH METHODS
      // ====================================================================
        // TODO: remove once callable via link
        // TODO: can I add methods to a module, when accessing the module from another module???
        App.translate = priv.translate;

        // prefix instance-ids, pass JSON, trigger("create")
        App.renderGadgets(gadget);

      // ====================================================================
      //                            INITIALIZE
      // ====================================================================
        priv.initialize(App.settings.language_current);
      };

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

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

        window.fallbackLoader.deferreds.push(def);
        window.fallbackLoader.args.push(priv.gadget);
      } else {
        // prefix instance-ids, pass JSON
        priv.deferred_setup_translations(priv.gadget);
      }
    }

  // return response object
  return response;
  }
);
