(function($) {

  /**
  * Partner object 
  **/
  var Partner = function(anchor, options) {
    var obj = this;
    obj.anchor = $(anchor);
    obj.options = options;

    obj.iframe = obj.anchor.children('iframe');
    obj.status = obj.anchor.children('#status');
    obj.action = obj.anchor.children('#action');
    
    /* loading lock (yes, this is atomic) */
    obj.mutex = false;

    /* Hide iframe  */
    obj.iframe.hide();

    /* Click handler toggle for actions */
    obj.action.click(function() {
      var status = obj.getStatus();
      if(status == "cookie" || status == "nocookie") {
        obj.optout();
      } else if(status == "optedout") {
        obj.optin();
      } else {
        obj.call('status');
      }
    }); 

    /* Opt-out directly */
    obj.optout = function() {
      obj.call("optout");
    } 

    /* Opt-in directly */
    obj.optin = function() {
      obj.call("optin");
    }

    /* Call partner and get status */
    obj.call = function(action) {

      /* if we're already loading, bail */
      if(!obj.mutex) { 
        obj.mutex = true;
      } else {
        return;
      }
      
      /* reset frame */
      obj.resetFrame();

      var src = options.srcStatus;

      if(action == "optout") {
        src = options.srcOptout;
        src += obj.getToken();
      } else if(action == "optin") {
        src = options.srcOptin;
        src += obj.getToken();
      }

      /* display loading message */ 
      obj.status.text("Contacting partner's opt-out server...");
      obj.action.text("");
      obj.action.css("cursor", "default");
      obj.anchor.fadeTo("fast", 0.33);
   
      /* Make call to partner server */
      obj.iframe.attr('src', src);
    
      /* Set timeout for call to partner server */ 
      setTimeout(obj.confirmLoad, 4000);
    }

    /* Partner call load timeout */
    obj.confirmLoad = function() {
      if(!obj.getStatus()) {
        obj.iframe.attr('src', ''); 
        obj.status.html("<b>Unable to connect</b> to partner's opt-out server");
        obj.action.text("Try to re-connect now");
      } else {
        obj.status.html(obj.getMessage());
        obj.action.text(obj.getAction());
      }
      obj.anchor.fadeTo("fast", 1);
      obj.action.css("cursor", "pointer");
      /* release lock */
      obj.mutex = false;
    }
 
    /* Action accessor */
    obj.getAction = function() {
      return obj.iframe.contents().find('#action').val();
    }

    /* Message accessor */
    obj.getMessage = function() {
      return obj.iframe.contents().find('#message').val();
    }

    /* Token accessor */
    obj.getToken = function() {
      return obj.iframe.contents().find('#token').val();
    }
    
    /* Status accessor */
    obj.getStatus = function() {
      return obj.iframe.contents().find('#status').val();
    }
    
    obj.resetFrame = function() {
      obj.iframe.contents().find('#status').val('');
    }

  };

  /**
  * loadPartner
  * Creates a Partner object and associates it with the given 
  * partner div.
  * */
  $.fn.loadPartner = function() {
    return this.each(function() {
      var obj = $(this);

      /* Build options based on HTML */
      var srcStatus = obj.children('#srcStatus').attr('href');
      var srcOptin = obj.children('#srcOptin').attr('href');
      var srcOptout = obj.children('#srcOptout').attr('href');

      var options = { srcStatus : srcStatus,
                      srcOptin : srcOptin,
                      srcOptout : srcOptout };

      /* Create and call the partner for initial status/token */
      var partner = new Partner(this, options);
      partner.call("none");

      /* store the partner object in div */
      obj.data('partner', partner);

    });
  }

  /**
  * optout
  * Optout of this partner div by looking up the 
  * related object and opting out of that.
  * */
  $.fn.optout = function() {
    return this.each(function() {
      var obj = $(this);
      var partner = obj.data('partner');
      partner.optout();
    });
  };

}) (jQuery);
