/**
 **  Copyright (c) 2005 Snapvine, LLC. All rights reserved.
 **
 ** THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF Snapvine, LLC
 **    The copyright notice above does not evidence any
 **    actual or intended publication of such source code.
 **/

/** This library contains a  polling class built on top of the rails
 ** prototype library. This class polls the snapvine server to determine when
 ** a session has been completed.
 **/

var SvPollerLib = {
  Version: '0.0.2',
  emptyFunction: function() {},
  errorFunction: function(error) {
    alert("A server error was encountered, please try again in a few minutes");
  }
}

/** VERSIONS **/
var VALIDATE_DIALOUT    = 1;
var VALIDATE_DIALIN     = 2;
var SNAPWIDGET_DIALIN   = 3;
var MYSPACE_AUTOINSERT  = 4;
var BEBO_AUTOINSERT     = 5;
var SIMPLE_DIALIN       = 6;
var RECORD_DIALOUT      = 7;
var TAGGED_AUTOINSERT   = 8;
var FREEWEBS_REFRESH    = 9;
var STARTED_DIALIN      = 10;
var MYSPACE_BULLETIN	= 11;
var FREEWEBS_LOGIN      = 12;
var FREEWEBS_SIGNOUT    = 13;
var FREEWEBS_INSERT     = 14;
var FLIXSTER_AUTOINSERT = 15;

var SIMPLE_POLLER       = 16; // Use start_url

/** STATUS **/
var STATUS_ERROR      = "-1";
var STATUS_COMPLETE   = "0";
var STATUS_RUNNING    = "1";
var STATUS_FAILED     = "2";
// Detailed status for AUTOINSERTERS
var STATUS_EINTERNAL  = "3";
var STATUS_EMARKUP    = "4";
var STATUS_ETIMEOUT   = "5"
var STATUS_EPRESENT   = "6";
var STATUS_EAUTH      = "7";
var STATUS_ELOGGEDOUT = "8";


var SvPoller = Class.create();
SvPoller.prototype = {
  initialize: function(options)
  {
    this.setOptions(options);
    this.terminate = false;
  },

  start: function()
  {
    var url = this.get_start_url();
    if(url)
    {
      new Ajax.Updater(this.options.updateStatusElement,url,
      {asynchronous:true,
                      evalScripts:true,
                      onComplete:(function(request){this.pollDone(request, true)}).bind(this)});
    }
    else
    {
      this.sendPoll();
    }
  },

  stop: function()
  {
    this.terminate = true;
  },

  setOptions: function(options) {
    this.options = {
      version: VALIDATE_DIALOUT,
      updateStatusElement: null,
      onTerminateDone: null,
      onComplete: null,
      onStarted: null,
      onError: null,
      timeout: 5000,
      start_url: null,
      poll_url: null,
      poll_token: null,
      ext_options: {}
    };

    Object.extend(this.options, options || {});
    // allow callers to pass in a polling token
    this.poll_token = this.options.poll_token;  
    // Small shortcut for readability
    this.ext_options = this.options.ext_options;
  },


  pollDone: function(request, firstPoll)
  {
    // alert("resp: " + request.status);

    if (request.status != 200)
    {
      this.terminate = true;
      var errorFunc = this.options.onError || Prototype.errorFunction;
      errorFunc();
      return;
    }

    switch (request.getResponseHeader("process-status"))
    {
      case STATUS_ERROR:
      {
        this.terminate = true;
        var errorFunc = this.options.onError || Prototype.errorFunction;
        errorFunc();
        break;
      }

      case STATUS_COMPLETE:
      {
        this.terminate = true;
        var onComplete = this.options.onComplete || Prototype.emptyFunction;
        onComplete(true);
        break;
      }

      case STATUS_FAILED:
      {
        this.terminate = true;
        var onComplete = this.options.onComplete || Prototype.emptyFunction;
        onComplete(false);
        break;
      }

      case STATUS_RUNNING:
      {
        if (this.terminate)
        {
          var doneFunc = this.options.onTerminateDone || Prototype.emptyFunction;
          doneFunc();
        }
        else
        {
          if (firstPoll)
          {
            // Before the polling begins we must intitialize our state to include
            // the correct information for the poller
            this.initPollingState(request);
          }

          setTimeout((function() {this.sendPoll()}).bind(this), this.options.timeout);
        }
        break;
      }

      case STATUS_EINTERNAL:
      case STATUS_EMARKUP:
      case STATUS_ETIMEOUT:
      case STATUS_EPRESENT:
      case STATUS_EAUTH:
      case STATUS_ELOGGEDOUT:
      {        
        this.terminate = true;
        var errorFunc = this.options.onError || Prototype.errorFunction;
        errorFunc(request.getResponseHeader("process-status"));
        break;
      }

      default:
      {
        break;
      }
    }
  },

  initPollingState: function(request)
  {
    var startedFunc = this.options.onStarted || Prototype.emptyFunction;

    this.poll_token = request.getResponseHeader("poll_token");

    if (this.usingDialin())
    {      
      // When the user is dialing in we will get the phonenumber and code they are going to
      // use after our start_validation poll
      this.lease_phone = request.getResponseHeader("lease_phone");
      this.lease_code = request.getResponseHeader("lease_code");

      var expire_sec = request.getResponseHeader("lease_expire_seconds");
      var phone_formatted = request.getResponseHeader("lease_phone_formatted");

      startedFunc(phone_formatted, this.lease_code, expire_sec);
    }
    else
    {
      startedFunc(null, null, null);
    }
  },

  usingDialin: function()
  {
    return ((VALIDATE_DIALIN == this.options.version) ||
            (SNAPWIDGET_DIALIN == this.options.version) ||
      (SIMPLE_DIALIN == this.options.version)
      );
  },

  sendPoll: function()
  {
    var url = this.get_poll_url();

    new Ajax.Updater(this.options.updateStatusElement,
                     url,
      {asynchronous:true,
       evalScripts:true,
       onComplete:(function(request){this.pollDone(request, false)}).bind(this)});
  },

  get_start_url: function()
  {
    switch (this.options.version)
    {
      case VALIDATE_DIALIN:  return '/user/start_validation?method=dialin&cc='+this.ext_options.countrycode;
      case SNAPWIDGET_DIALIN: return '/account/start_sharedcomment?cc='+this.ext_options.countrycode;
      case MYSPACE_AUTOINSERT:
        return "/gadget/auto_add_myspace?skin_id="+this.ext_options.skin_id
          +"&myspace_email="+this.ext_options.myspace_email
          +"&myspace_password="+this.ext_options.myspace_password
          +"&myspace_section="+this.ext_options.myspace_section
          +"&allow_dup="+this.ext_options.allow_dup
          +"&key="+this.ext_options.key
          +"&ref="+this.ext_options.ref;

      case BEBO_AUTOINSERT:
      {
        var url = "/gadget/start_bebo_scrape?skin_id="+this.ext_options.skin_id;
        if (this.ext_options.login != null)
          url += "&login=" + this.ext_options.login;
        if (this.ext_options.password != null)
          url += "&password=" + this.ext_options.password;
        if (this.ext_options.name != null)
          url += "&name=" + this.ext_options.name;
        return url;
      }
      case TAGGED_AUTOINSERT: return "/gadget/start_tagged_scrape?skin_id="+this.ext_options.skin_id;
      case FREEWEBS_LOGIN:
        return  "/gadget/freewebs_login?login=" + this.ext_options.login + "&password=" + this.ext_options.password;
      case FREEWEBS_REFRESH: return "/gadget/freewebs_refresh"; 
      case FREEWEBS_SIGNOUT: return "/gadget/freewebs_logout"; 
      case FREEWEBS_INSERT:
         return "/gadget/freewebs_insert?skin_id="+this.ext_options.skin_id+"&page_id="+this.ext_options.page_id;
      case MYSPACE_BULLETIN:
        return "/account/auto_post_bulletin?myspace_email="+this.ext_options.myspace_email
          +"&myspace_password="+this.ext_options.myspace_password
          +"&subject="+this.ext_options.myspace_bulletin_subject
          +"&body="+this.ext_options.myspace_bulletin_body;

      case FLIXSTER_AUTOINSERT:
      {
        url = "/gadget/start_flixster_scrape?skin_id="+this.ext_options.skin_id;
        url += "&login=" + this.ext_options.login;
        url += "&password=" + this.ext_options.password;
        url += "&bulletin=" + this.ext_options.bulletin;
        url += "&message=" + this.ext_options.message;
        return url;
      }

      case SIMPLE_POLLER: 
      case SIMPLE_DIALIN: 
      case RECORD_DIALOUT: return this.options.start_url;
      case STARTED_DIALIN: return null;
      default: return '';
    }
  },


  get_poll_url: function()
  {
    if(this.options.poll_url)
    {
      delim = "?";
      if(this.options.poll_url.indexOf("?")!=-1)
      {
        delim = "&";
      }
      return this.options.poll_url + delim + "token=" + this.poll_token;
    }
    
    switch (this.options.version)
    {
      case VALIDATE_DIALOUT:
      case VALIDATE_DIALIN:
      case SNAPWIDGET_DIALIN:
      case SIMPLE_DIALIN:
      case STARTED_DIALIN:
      case RECORD_DIALOUT:    
      case MYSPACE_AUTOINSERT: 
      case BEBO_AUTOINSERT:
      case MYSPACE_BULLETIN:
      case FREEWEBS_INSERT:
      case FLIXSTER_AUTOINSERT:
      case SIMPLE_POLLER:
               return '/poll/status?token=' + this.poll_token;
      case FREEWEBS_LOGIN:
      case FREEWEBS_REFRESH:
               return '/poll/freewebs_getpages?token=' + this.poll_token;
      case FREEWEBS_SIGNOUT:
               return '/poll/freewebs_logout?token=' + this.poll_token;
      case TAGGED_AUTOINSERT:
               return '/poll/tagged_insert?token=' + this.poll_token;
      default: return '';
    }
  }
};

var PollerInterface = Class.create();
PollerInterface.prototype = {
  initialize: function(options)
  {
    this.setOptions(options);

    this.poll = new SvPoller( {
                                      dialoutPhone: options.dialoutPhone,
                                      start_url: options.start_url,
                                      poll_url: options.poll_url,
                                      updateStatusElement: this.options.statusElement,
                                      poll_token: this.options.poll_token,
                                      onTerminateDone: (function() {this.poll_terminated()}).bind(this),
                                      onComplete: (function(success) {this.func_done(success)}).bind(this),
                                      onError: (function(error) {this.func_error(error)}).bind(this),
                                      onStarted: (function(p,c,e) {this.func_started(p,c,e)}).bind(this),
                                      version: options.version,
                                      ext_options: options.ext_options
                                  });
    this.poll.start();
  },

  setOptions: function(options) {
    this.options = {
      statusElement: null,
      startFunction: null,
      completeFunction: null,
      errorFunction: null,
      start_url: null,
      poll_url: null,
      poll_token: null
  };

  Object.extend(this.options, options || {});
  },


  stop: function()
  {
    if (this.poll)
    {
      this.poll.stop();
    }
  },

  is_terminated: function()
  {
    return this.poll && this.poll.terminate;
  },

  poll_terminated: function()
  {
    if (this.poll)
    {
      this.poll = null;
    }
  },

  func_started: function(lease_phone, lease_code, lease_expire)
  {
    var startedFunc = this.options.startFunction || Prototype.emptyFunction;
    startedFunc(lease_phone, lease_code, lease_expire);
  },

  func_done: function(success)
  {
    var doneFunc = this.options.completeFunction || Prototype.emptyFunction;
    doneFunc(success);
  },

  func_error: function(error)
  {

    var errFunc = this.options.errorFunction || Prototype.emptyFunction;
    errFunc(error);
  }

};


function do_poll(url, data, interval, timeout, callback)
{
  interval = interval * 1000;
  timeout = timeout * 1000;
  
  opt = {
    json: true,
    get_progress_info: false
  };
  Object.extend(opt, data || {});
  
  interval_timer = setInterval(function(){
    $.getJSON(url, data, (function(json){
      status_code = json.status;
      if ((status_code != "0") && (!status_code)) {
        status_code = json.process_status;
      }
      switch (status_code) {
        case 0:
          clearInterval(interval_timer);
          clearTimeout(to);
          callback(true, json);
          break;
        case 1:
          /* fall thru */
        case 10:
          /* fall thru */
        case 11:
          if (opt.get_progress_info) {
            callback(false, json);
          }
          break;
        default:
          clearInterval(interval_timer);
          clearTimeout(to);
          callback(false, json);
          break;
      }
    }));
  }, interval);

  var to = setTimeout(function(){
    clearInterval(interval_timer);
    callback(false, null);
  },timeout);

  return interval_timer;
}
