//var Rox_disable = true;
var Rox_disable = false;
/*roxlib for adelivery
just a part of the roxlib.js
*/
/*prototype begin*/
var Class = {
  create: function() {
    return function() {
      this.initialize.apply(this, arguments);
    }
  }
}
Object.extend = function(destination, source) {
  for (property in source) {
    destination[property] = source[property];
  }
  return destination;
}
var $A = function(iterable) {
  if (!iterable) return [];
  if (iterable.toArray) {
    return iterable.toArray();
  } else {
    var results = [];
    for (var i = 0; i < iterable.length; i++)
      results.push(iterable[i]);
    return results;
  }
}
Function.prototype.bind = function() {
  var __method = this, args = $A(arguments), object = args.shift();
  return function() {
    return __method.apply(object, args.concat($A(arguments)));
  }
}
function $(element) {
  if (arguments.length > 1) {
    for (var i = 0, elements = [], length = arguments.length; i < length; i++)
      elements.push($(arguments[i]));
    return elements;
  }
  if (typeof element == 'string')
    element = document.getElementById(element);
  if(typeof Element != 'undefined'&& Element.extend)
    return Element.extend(element);
  else
    return element;
}
/*prototype end*/
var Rox = {
  Version: '2.0.0'
};
Rox.PeerCtrl = Class.create();
Rox.PeerCtrl.prototype = {
  initialize:  function(){
    this.adapterVersionLow = false;
    this.adapter_ = null;
    this.errorReportUrl = '';
    this.peerAddr = '';
    this.openedChannels = new Array();
    this.isAdapterAvailable = false;
  },
  init: function(domain, errorReportUrl, version){
    if(!domain)
      return -3;

    if(this.isAvailable())
      return 1;
//alert("before new");
    try{
      if (window.ActiveXObject){
        this.adapter_ = new ActiveXObject("PeerAdapterE.Controller.1");
      }else{
        this.adapter_ = new PeerController();
      }
    }catch(e){
      //alert(e.number);
      this.adapter_ = null;
      return -2;
    }
//alert("after new ActiveXObject(PeerAdapterE.Controller.1) ");
    if(version){
      try{
        this.adapterVersion = this.adapter_.AdapterVersion;
        var ver = this.adapterVersion.match(/\d+\.\d+\.\d+\.\d+/);
        var version_infos = String(ver).split(".");
        for(var i=0; i<4; i++){
          var vi = parseInt(version[i]);
          var uservi = parseInt(version_infos[i]);
          if(uservi < vi){
            this.adapterVersionLow = true;
            return 1;
            break;
          }else if(uservi > vi)
            break;
        }
      }catch(e){
        this.adapter_ = null;
        return -1;
      }
    }

    try{
      this.adapter_.Domain = String(domain);
      if(errorReportUrl) this.adapter_.ErrorReportUrl = String(errorReportUrl);
      this.errorReportUrl = String(errorReportUrl);

      if (window.ActiveXObject){
        this.adapter_.InitializeEx();
      }else{
        this.adapter_.InitializeEx();
      }
    }catch(e){
      try{this.adapter_.ReportError(String(errorReportUrl));}catch(e){}
      this.adapter_ = null;
      return -1;
    }
//alert("after InitializeEx");
    try{
      this.peerAddr=this.adapter_.EnsurePeerServiceWithoutConf(
                            this.adapter_.Executable,
                            this.adapter_.Configuration,
                            this.adapter_.InstanceID);
    }catch(e){
      try{
        this.adapter_.CollectDiagnosticInformation(3);
        this.adapter_.ReportError(this.errorReportUrl);
      }catch(e){}
      this.adapter_ = null;
      return -4;
    }
//alert("after EnsurePeerService");
    this.isAdapterAvailable = true;
    return 1;
  },
  reset:  function(){
    this.adapterVersionLow = false;
    this.adapter_ = null;
    this.errorReportUrl = '';
    this.peerAddr = '';
    this.openedChannels = new Array();
    this.isAdapterAvailable = false;
  },
  login:  function(user, pass, session_server){
    if(!this.isAvailable()) return "";
    try{
      return this.adapter_.Login(user, pass, session_server);
    }catch(e){
      return "";
    }
  },
  queryOperationStatus: function(operationID){
    try{
      return this.adapter_.QueryOperationStatus(operationID);
    }catch(e){
      return "";
    }
  },
  isAvailable:  function(){
    return this.isAdapterAvailable && this.isPeerAvailable();
  },
  isPeerAvailable:  function(){
    try{
      return this.adapter_.IsPeerServiceAvailable();
    }catch(e){
      try{this.adapter_.ReportError(this.errorReportUrl);}catch(e){}
      return 0;
    }
  },
  queryCurrentLogin:  function(){
    if(!this.isAvailable()) return "";
    try{
      return this.adapter_.QueryCurrentLogin();
    }catch(e){
      return "";
    }
  },
  getAddress:  function(){
    return this.peerAddr;
  },
  getVersion:  function(){
    if(!this.adapter_) return null;
    try{
      return this.adapter_.Version;
    }catch(e){
      return null;
    }
  },
  getAdapterVersion:  function(){
    if(!this.adapter_) return null;
    return this.adapter_.AdapterVersion;  
  },
  openChannelEx:  function(channelId, typeStr, hasSig, sigUrl, fileName){
    if(!channelId) return -3;
    if(!this.isAvailable()) return 0;
    if(this.findOpenedChannel(channelId) < 0)
      try{
        if(typeStr == "type=download")
          return this.adapter_.OpenChannelEx(channelId, 'type=download', hasSig, sigUrl, fileName);
        else if(typeStr == "type=stream")
          return this.adapter_.OpenChannelEx(channelId, 'type=stream', hasSig, sigUrl, "");
        else if(typeStr == "type=url")
          return this.adapter_.OpenChannelEx(channelId, 'type=url', hasSig, sigUrl, "");
        else if(typeStr == "type=urldownload")
          return this.adapter_.OpenChannelEx(channelId, 'type=urldownload', hasSig, sigUrl, fileName);
        else if(typeStr == "type=normal")
          return this.adapter_.OpenChannelEx(channelId, 'type=normal', hasSig, sigUrl, "");
        else
          return -3;
      }catch(e){
        try{this.adapter_.ReportError(this.errorReportUrl);}catch(e){}
        return -1;
      }
    return -2;
  },
  closeChannel:  function(channelId){
    if(!channelId) return -3;
    if(!this.isAvailable()) return 0;
    var index = this.findOpenedChannel(channelId);
    if(index >= 0) this.removeOpenedChannel(index);
    try{
      return this.adapter_.CloseChannel(channelId);
    }catch(e){
      try{this.adapter_.ReportError(this.errorReportUrl);}catch(e){}
      return -1;
    }
  },
  status:    function(channelId){
    if(!this.isAvailable()) return null;
    try{
      return this.adapter_.StatChannel(channelId);
    }catch(e){
      try{this.adapter_.ReportError(this.errorReportUrl);}catch(e){}
      return null;
    }
  },
  tell:    function(channelId){
    if(!this.isAvailable()) return null;
    try{
      return this.adapter_.TellChannel(channelId);
    }catch(e){
      //try{this.adapter_.ReportError(this.errorReportUrl);}catch(e){}
      return null;
    }
  },
  shutdown:  function(){
    if(!this.isAvailable()) return 0;
    this.closeAllChannels();
    try{
      this.adapter_.Shutdown();
      return 1;
    }catch(e){
      try{this.adapter_.ReportError(this.errorReportUrl);}catch(e){}
      return -1;
    }
  },
  closeAllChannels:  function(){
    var cid = '';
    if(this.isAvailable())
      while(cid = this.openedChannels.pop())
        try{
          this.adapter_.CloseChannel(cid);
        }catch(e){
          try{this.adapter_.ReportError(this.errorReportUrl);}catch(e){}
        }
  },
  openAsx:   function(asxId){
    if(!this.isAvailable()) return false;
    try{
      this.adapter_.OpenAsx(asxId);
      return true;
    }catch(e){
      try{this.adapter_.ReportError(this.errorReportUrl);}catch(e){}
      return false;
    }
  },
  closeAsx:  function(asxId){
    if(!this.isAvailable()) return false;
    try{
      this.adapter_.CloseAsx(asxId);
      return true;
    }catch(e){
      try{this.adapter_.ReportError(this.errorReportUrl);}catch(e){}
      return false;
    }
  },
  registerAsx:  function(asxUrl, cookie){
    if(!this.isAvailable()) return null;
    try{
      return this.adapter_.RegisterAsx(asxUrl, cookie);
    }catch(e){
      try{
        return this.adapter_.RegisterAsx(asxUrl);
      }catch(e){
        try{this.adapter_.ReportError(this.errorReportUrl);}catch(e){}
        return null;
      }
    }
  },
  unregisterAsx: function(asxId){
    if(!this.isAvailable()) return false;
    try{
      this.adapter_.UnregisterAsx(asxId);
      return true;
    }catch(e){
      try{this.adapter_.ReportError(this.errorReportUrl);}catch(e){}
      return false;
    }
  },
  endSession: function(){
    if(!this.isAvailable()) return false;
    try{
      this.adapter_.EndSession();
      return true;
    }catch(e){
      try{this.adapter_.ReportError(this.errorReportUrl);}catch(e){}
      return  false;
    }
  },
  getSessionId: function(){
    if(!this.adapter_) return null;
    try{
      return this.adapter_.SessionID;
    }catch(e){
      return null;
    }
  },
  getDomain: function(){
    if(!this.adapter_) return null;
    try{
      return this.adapter_.Domain;
    }catch(e){
      return  null;
    }
  },
  getErrorReportUrl: function(){
    if(!this.adapter_) return null;
    try{
      return this.adapter_.ErrorReportUrl;
    }catch(e){
      return null;
    }
  },
  putErrorReportUrl: function(url){
    if(!url) return false;
    if(!this.adapter_) return false;
    try{
      this.adapter_.ErrorReportUrl = String(url);
      this.errorReportUrl = String(url);
      return true;
    }catch(e){
      return false;
    }
  },
  getChannelUrl: function(channelId, extension, flag){
    if(!this.adapter_) return null;
    return this.adapter_.GetChannelUrl(channelId, extension, flag);
  },
  seekChannel: function(channelId, p, flag){
    if(!this.adapter_) return;
    try{
      this.adapter_.SeekChannel(channelId, p, flag);
    }catch(e){}
  },
  findDefaultPeerService: function(){
    if(!this.adapter_) return null;
    try{
      return this.adapter_.FindDefaultPeerService();
    }catch(e){
      try{this.adapter_.ReportError(this.errorReportUrl);}catch(e){}
      return null;
    }
  },
  getPeerID: function(){
    if(!this.adapter_) return null;
    try{
      return this.adapter_.PeerID;
    }catch(e){
      return null;
    }
  },
  getInstanceID: function(){
    if(!this.adapter_) return null;
    try{
      return this.adapter_.InstanceID;
    }catch(e){
      return null;
    }
  },
  collectDiagnosticInformation: function(flag){
    flag = parseInt(flag);
    if(flag>3 || flag<1) flag = 3;
    if(!this.adapter_) return;
    try{this.adapter_.CollectDiagnosticInformation(flag);}catch(e){}
  },
  reportError: function(errorReportUrl){
    if(!this.adapter_) return;
    try{
    if(errorReportUrl){
      this.adapter_.ReportError(errorReportUrl);
    }else{
      this.adapter_.ReportError(this.errorReportUrl);
    }
    }catch(e){}
  },

  addOpenedChannel: function(channelId){
    this.openedChannels.push(channelId);
  },

//private functions
  findOpenedChannel:   function(channelId){
    var len = this.openedChannels.length;
    for(var i=0; i < len; i++){
      if(this.openedChannels[i] == channelId)
        return i;
    }
    return -1;   // do not find channel
  },
  removeOpenedChannel:  function(index){
    this.openedChannels.splice(index, 1);
  }
}
Rox.peerCtrl_ = null;
Rox.PeerCtrl.instance = function(){
  if(!Rox.peerCtrl_){
    Rox.peerCtrl_ = new Rox.PeerCtrl();
  }
  return Rox.peerCtrl_;
}

/******************************************************************************
*  Utility Class
*/
Rox.TimeoutCall = Class.create();
Rox.TimeoutCall.prototype = {
  initialize: function(){
    this.actionCall = null;
    this.interval = 5000;

    this.timeoutId = null;
  },
  init: function(actionCall, interval){
    if(actionCall) 
      this.actionCall = actionCall;
    else 
      alert("Rox.TimeoutCall: initialize no actionCall");

    if(interval) 
      this.interval = parseInt(interval);

    this.timeoutId = null;
  },
  setInterval: function(interval){
    this.interval = parseInt(interval);
  },
  setActionCall: function(actionCall){
    this.actionCall = actionCall;
  },
  start: function(){
    if(!this.actionCall){
      alert("Rox.TimeoutCall.start(): have no actionCall");
      return false;
    }

    this.timeoutId = setTimeout(this.act.bind(this), 100);
    return true;
  },
  stop: function(){
    if(this.timeoutId){
      clearTimeout(this.timeoutId);
      this.timeoutId = null;
    }
  },
  act: function(){
    if(this.timeoutId){
      clearTimeout(this.timeoutId);
      this.timeoutId = null;
    }

    var ret = this.actionCall();
    if(ret == true){
      this.timeoutId = setTimeout(this.act.bind(this), this.interval);
    }else{
      this.timeoutId = null;
    }

    return ret;
  }
}

Rox.XmlParser = Class.create();
Rox.XmlParser.prototype = {
  initialize: function(){
    this.xmlParser_ = null;
  },
  init: function(){
    this.getParser_();
    if(!this.xmlParser_) return false;
    return true;
  },
  getParser: function(){
    this.getParser_();
    return this.xmlParser_;
  },
  loadXML: function(xml){
    return this.loadXML_(xml);
  },
  parseFromString: function(xml){
    return this.loadXML_(xml);
  },
  /*
    private functions begin
  */
  loadXML_: function(xml){
    this.getParser_();
    if(!this.xmlParser_) return null;

    if (window.ActiveXObject){
      this.xmlParser_.loadXML(xml);
      return this.xmlParser_;
    }else{
      return this.xmlParser_.parseFromString(xml, "text/xml");
    }
  },
  getParser_: function(){
    if(this.xmlParser_) return;

    if (window.ActiveXObject){
      try{
        this.xmlParser_ = new ActiveXObject("Msxml2.XMLDOM");
        this.xmlParser_.async = "false";
      } catch(e) {
        try {
          this.xmlParser_ = new ActiveXObject("Microsoft.XMLDOM");
          this.xmlParser_.async = "false";
        } catch(e) {
          // alert(e);
          this.xmlParser_ = null;
        }
      }
    }else{
      this.xmlParser_ = new DOMParser();
    }
  }
}
Rox.xmlParser_ = null;
Rox.XmlParser.instance = function(){
  if(!Rox.xmlParser_){
    Rox.xmlParser_ = new Rox.XmlParser();
    Rox.xmlParser_.init();
  }
  return Rox.xmlParser_;
}

Rox.PeerTell = Class.create();
Rox.PeerTell.prototype = {
  initialize: function(){
    this.peerCtrl_ = Rox.PeerCtrl.instance();
    this.xmlParser_ = Rox.XmlParser.instance();
    this.total = 1000000;
    this.byterate = 5600;
    this.pos = 0;
    this.readable = 0;
    this.downloaded = 0;
  },
  init: function(){
    if(!this.xmlParser_.init()) return 0;
    return 1;
  },
  tell: function(channelId){
    var tellstr = this.peerCtrl_.tell(channelId);
    if( tellstr == null || tellstr == "") return false;

    var xmlDoc = this.xmlParser_.loadXML(tellstr);
    if(!xmlDoc) return false;

    var root = xmlDoc.getElementsByTagName("tell")[0];
    if(!root) return false;

    this.total = parseInt(root.getAttribute("total"));
    this.byterate = parseInt(root.getAttribute("bitrate")) / 8;
    this.pos = parseInt(root.getAttribute("pos"));
    this.readable = parseInt(root.getAttribute("readable"));
    this.downloaded = parseInt(root.getAttribute("downloaded"));
    return true;
  }
}

Rox.OpenCtrl = Class.create();
Rox.OpenCtrl.prototype = {
  initialize: function(){
    this.listener = null;
    this.cId = '';
    this.operationID = '';
    this.peerCtrl_ = Rox.PeerCtrl.instance();
    this.tcall_ = new Rox.TimeoutCall();
    this.tcall_.init(this.query_.bind(this), 1000);
  },
  init: function(l){
    this.listener = l;
  },
  open: function(c, type, hasSig, sigUrl, fileName){
    this.cId = c;
    var ret = this.peerCtrl_.openChannelEx(c, type, hasSig, sigUrl, fileName);
    if(typeof ret != "string")
      return ret;
    this.operationID = ret;
    this.tcall_.start();
    return 1;
  },
  query_: function(){
   var ret = this.peerCtrl_.queryOperationStatus(this.operationID);
   if(ret.indexOf("running") != -1){
      return true;
   }else if(ret.indexOf("error") != -1){
      this.operationID = '';
      this.peerCtrl_.reportError();
      this.listener.failedToOpen(this.cId, ret);
      return false;
   }else if(ret.indexOf("completed") != -1){
      this.operationID = '';
      if(ret.indexOf(":") != -1) this.cId = (ret.split(":"))[1];
      this.peerCtrl_.addOpenedChannel(this.cId);
      this.listener.afterOpen(this.cId);
      return false;
   }else return false;
  },
  endMember: function(){}
}

Rox.CloseCtrl = Class.create();
Rox.CloseCtrl.prototype = {
  initialize: function(){
    this.operationID = '';
    this.peerCtrl_ = Rox.PeerCtrl.instance();
    this.tcall_ = new Rox.TimeoutCall();
    this.tcall_.init(this.query_.bind(this), 1000);
  },
  close: function(c){
    var ret = this.peerCtrl_.closeChannel(c);
    if(typeof ret != "string")
      return ret;
    this.operationID = ret;
    this.tcall_.start();
    return 1;
  },
  query_: function(){
   var ret = this.peerCtrl_.queryOperationStatus(this.operationID);
   if(ret.indexOf("running") != -1){
      return true;
   }else if(ret.indexOf("error") != -1){
      this.operationID = '';
      this.onFailedToClose();
      return false;
   }else if(ret.indexOf("completed") != -1){
      this.operationID = '';
      this.onAfterClose();
      return false;
   }else return false;
  },
  onFailedToClose: function(){},
  onAfterClose: function(){},
  endMember: function(){}
}

Rox.PlayCtrl2 = Class.create();
Rox.PlayCtrl2.prototype = {
  initialize: function(){
    this.cId = '';
    this.asxId = '';
    this.postfix = '';
    this.waitBufferCall = null;
    this.bufferMark = '';

    this.peerCtrl_ = Rox.PeerCtrl.instance();
    this.peerTell_ = new Rox.PeerTell();
    this.openCtrl_ = new Rox.OpenCtrl();
    this.openCtrl_.init(this);
    this.closeCtrl_ = new Rox.CloseCtrl();

    this.timeoutCall_ = new Rox.TimeoutCall();
    this.timeoutCall_.init(this.waitBuffering_.bind(this), 2000);

    this.busy = false;
  },
  register: function(playerName, wbc, interval){
    if(wbc){
      if(typeof(wbc) == "function")
        this.waitBufferCall = wbc;
      else return false;
    }
    if(interval)
      this.timeoutCall_.setInterval(interval);
    return true;
  },
  openChannel: function(cid, postfix){
    return this.open(cid, postfix, "nobuffer");
  },
  open: function(cid, postfix, buffermark){
    if(!cid || !postfix){
      alert("Rox.PlayCtrl2.open(): no parameters");
      return -100;
    }
    if(!buffermark) buffermark = '';
    postfix = postfix.toLowerCase();
    if( postfix != "asf" 
        &&postfix != "wmv"
        &&postfix != "avi"
        &&postfix != "flv"
        &&postfix != "rmvb"
        &&postfix != "rm"){
      alert("Unknown format");
      return -101;
    }

    if(!this.peerCtrl_.isAvailable()) return -2;
    if(!this.peerCtrl_.queryCurrentLogin()) return -3;

    if(this.busy) return -4;
    this.busy = true;

    this.timeoutCall_.stop();

    if(this.cId) this.closeCtrl_.close(this.cId);
    this.cId = '';

    if(this.asxId){
      this.peerCtrl_.closeAsx(this.asxId);
      this.peerCtrl_.unregisterAsx(this.asxId);
    }
    this.asxId = '';

    var ret = null;
    if(postfix == "asf")
      ret = this.openCtrl_.open(cid, "type=stream", false, "");
    else
      ret = this.openCtrl_.open(cid, "type=normal", false, "");

    if(ret != 1){
      this.busy = false;
      if(ret == -1) return 0;//failed to call interface
      else if(ret == -2) return -1;//opened already
      else return -200;
    }
    this.postfix = postfix;
    this.bufferMark = buffermark;
    return 1;
  },
  openUrl: function(cid, hasSig, sigUrl, postfix, buffermark){
    if(!cid || !postfix){
      alert("Rox.PlayCtrl2.openUrl(): no parameters");
      return -100;
    }
    if(!buffermark) buffermark = '';
    postfix = postfix.toLowerCase();
    if( postfix != "asf" 
        &&postfix != "wmv"
        &&postfix != "avi"
        &&postfix != "flv"
        &&postfix != "rmvb"
        &&postfix != "rm"){
      alert("Unknown format");
      return -101;
    }

    if(!this.peerCtrl_.isAvailable()) return -2;
    if(!this.peerCtrl_.queryCurrentLogin()) return -3;

    if(this.busy) return -4;
    this.busy = true;

    this.timeoutCall_.stop();

    if(this.cId) this.closeCtrl_.close(this.cId);
    this.cId = '';

    if(this.asxId){
      this.peerCtrl_.closeAsx(this.asxId);
      this.peerCtrl_.unregisterAsx(this.asxId);
    }
    this.asxId = '';

    var ret = this.openCtrl_.open(cid, 'type=url', hasSig, sigUrl);
    if(ret != 1){
      this.busy = false;
      if(ret == -1) return 0;//failed to call interface
      else if(ret == -2) return -1;//be opened already
      else return -200;
    }
    this.postfix = postfix;
    this.bufferMark = buffermark;
    return 1;
  },
  openAsx: function(asxFileUrl){
    if(!asxFileUrl){
      alert("Rox.PlayCtrl2.openAsx(): asxFileUrl=null");
      return -100;
    }

    if(!this.peerCtrl_.isAvailable()){
      return -2;
    }

    if(!this.peerCtrl_.queryCurrentLogin()){
      return -3;
    }

    if(this.busy) return -1;
    this.busy = true;

    this.timeoutCall_.stop();

    if(this.cId) this.closeCtrl_.close(this.cId);
    this.cId = '';

    var cookie = document.cookie;
    var asxId = this.peerCtrl_.registerAsx(asxFileUrl, cookie);
    if(!asxId){
      this.busy = false;
      return -4;
    }

    if(this.asxId && this.asxId != asxId){
      this.peerCtrl_.closeAsx(this.asxId);
      this.peerCtrl_.unregisterAsx(this.asxId);
    }
    this.asxId = '';

    if(!this.peerCtrl_.openAsx(asxId)){
      this.busy = false;
      return -5;
    }

    this.asxId = asxId;
    this.postfix = "asx";
    this.busy = false;
    return 1;
  },
  getChannelUrl: function(){
    var flag = 1;
    var pfEx = this.postfix;
    if((this.postfix == "asf"||this.postfix == "wmv") && navigator.platform.indexOf("Win") == -1 && navigator.appName == "Netscape"){
      pfEx = "mms-asf";
      flag = 2;
    }
    if(this.postfix == "asx"){
      return this.peerCtrl_.getChannelUrl(this.asxId, pfEx, flag);
    }else{
      return this.peerCtrl_.getChannelUrl(this.cId, pfEx, flag);
    }
  },
  seek: function(time, flag){
    if(!this.cId) return;
    if(!flag) flag = 1;
    this.peerCtrl_.seekChannel(this.cId, time, flag);
  },
  waitBuffering_: function(){
    if(!this.waitBufferCall){
      return false;
    }
    //alert("wbc");
    this.peerTell_.tell(this.cId);
    return this.waitBufferCall(this.peerTell_.total, this.peerTell_.byterate, this.peerTell_.readable, this.peerTell_.downloaded);
  },
  stop: function(){
    if(this.busy) return false;
    this.busy = true;

    this.timeoutCall_.stop();

    if(this.cId) this.closeCtrl_.close(this.cId);
    this.cId = '';
    if(this.asxId){
      this.peerCtrl_.closeAsx(this.asxId);
      this.peerCtrl_.unregisterAsx(this.asxId);
    }
    this.asxId = '';
    this.busy = false;
    return true;
  },
  afterOpen: function(cid){
    this.cId = cid;
    if(this.bufferMark != "nobuffer")
      this.timeoutCall_.start();
    this.busy = false;
    try{this.onPostOpen(cid);}catch(e){alert(e);}
  },
  failedToOpen: function(cid, reason){
    this.busy = false;
    try{this.onFailedToOpen(cid);}catch(e){alert(e);}
  },

  onPostOpen: function(cid){},
  onFailedToOpen: function(cid){},
  endMember: function(){}
}

Rox.PlayCtrl_fake = Class.create();
Rox.PlayCtrl_fake.prototype = {
  initialize: function(){},
  register: function(playerName, wbc, interval){return false},
  openChannel: function(cid, postfix){return 0},
  open: function(cid, postfix, buffermark){return 0},
  openUrl: function(cid, postfix, buffermark){return 0},
  openAsx: function(asxFileUrl){return 0},
  getChannelUrl: function(){return null},
  seek: function(time, flag){},
  stop: function(){},
  onPostOpen: function(cid){},
  onFailedToOpen: function(cid){},
  endMember: function(){}
}


/****************************************************
 *  
 *  file download support
 *
 */

/**
 *  @class    file download control  
 *
 *  @brief    control file downloading and progress panel
 *
 *  @example: see also Rox.FileCenter
 *
 */
Rox.FileCtrl = Class.create();
Rox.FileCtrl.prototype = {
  initialize: function() {
    this.channelId = '';
    this.fileName = '';
    this.divId = '';
    this.beCanceled = false;
    this.type = '';
    this.hasSig = false;
    this.sigUrl = "";
    this.fileName = "";

    this.STATUS = {
      BLANK: 'blank',
      INIT: 'init',
      OPENING: 'opening',
      DOWNLOADING: 'downloading',
      DOWNLOADED: 'downloaded',
      SAVING: 'saving',
      FAILED: 'failed',
      COMPLETE: 'complete'
    };
    this.status = this.STATUS.BLANK;

    this.timeOutId = null;
    this.interval = 5000;

    this.peerCtrl_ = Rox.PeerCtrl.instance();
    this.peerTell_ = new Rox.PeerTell();
    
    this.openCtrl_ = new Rox.OpenCtrl();
    this.openCtrl_.init(this);
  },
  afterOpen: function(cid){
    this.channelId = cid;
    this.status = this.STATUS.DOWNLOADING;
    try{this.onPostOpen(cid);}catch(e){alert(e);}
    this.busy = false;

    this.onDownloading_();
  },
  failedToOpen: function(cid, reason){
    this.busy = false;
    try{this.onFailedToOpen(cid, reason);}catch(e){alert(e);}
  },

  onPostOpen: function(cid){},
  onFailedToOpen: function(cid, reason){},

  init: function(channelId, interval, fileName, divId, type, hasSig, sigUrl){
    if(!channelId){
      alert("you muse set first parameter to be channelId in Rox.FileCtrl.init()");
      return false;
    }

    this.type = type;
    this.channelId = channelId;
    this.hasSig = hasSig;
    this.sigUrl = sigUrl;
    this.fileName = fileName;

    if(interval) this.interval = parseInt(interval);

    if(fileName) this.fileName = fileName;

    if(divId){
      var div = document.getElementById(divId);
      if(!div){
        alert("there isn't DIV whith id "+divId);
        return false;
      }
      this.divId = divId;
    }

    this.status = this.STATUS.INIT;
    return true;
  },

  getStatus: function(){
    return this.status;
  },

  /*
  *  @brief  start download and calculate the progress
  *
  *  @param  interval, how offen to check the progress
  *  
  *  @return  true false
  */
  start:  function(){
    if(!this.channelId) 
      return false;

    if(!this.peerCtrl_.isAvailable()){
      alert("Can't download file because peer service is not available now.");  
      return false;
    }

    if(!this.peerCtrl_.queryCurrentLogin()){
      alert("Please login first!");
      return false;
    }

    var ret = null;
    if(this.type == "url"){
      ret = this.openCtrl_.open(this.channelId, 'type=urldownload', this.hasSig, this.sigUrl, this.fileName);
    }else{
      ret = this.openCtrl_.open(this.channelId, 'type=download', false, "", this.fileName);
    }
    if(ret == 1){
      //success
    }else if(ret == -2){
      //alert("This channel has been opened.");
      return false;
    }else if(ret == -1){
      //alert("Failed to open the channel "+this.channelId+" for downloading");
      return false; 
    }else if(ret == 0){
      //alert("No peer service");
      return false;
    }
    this.status = this.STATUS.OPENING;
    return true;
  },
  getChannelUrl: function(postfix){
    var flag = 1;
    var pfEx = postfix;
    if((postfix == "asf"||postfix == "wmv") && navigator.platform.indexOf("Win") == -1 && navigator.appName == "Netscape"){
      pfEx = "mms-asf";
      flag = 2;
    }
    return this.peerCtrl_.getChannelUrl(this.channelId, pfEx, flag);
  },

  onDownloading: function(){
    if(this.timeOutId){
      clearTimeout(this.timeOutId);
      this.timeOutId = null;
    }
    this.onDownloading_();
  },

  cancelDownload:  function(){
    if(this.timeOutId){
      clearTimeout(this.timeOutId);
      this.timeOutId = null;
    }

    this.onDownloadCanceled_(this.channelId);
    this.peerCtrl_.closeChannel(this.channelId);
    this.status = this.STATUS.BLANK;
  },
  closeChannel: function(){
    if(this.timeOutId){
      clearTimeout(this.timeOutId);
      this.timeOutId = null;
    }

    this.peerCtrl_.closeChannel(this.channelId);
  },

  onDownloading_: function(){
    this.peerTell_.tell(this.channelId);

    this.total = this.peerTell_.total;
    this.byterate = this.peerTell_.byterate;
    this.pos = this.peerTell_.pos;
    this.readable = this.peerTell_.readable;
    this.downloaded = this.peerTell_.downloaded;

    if(this.downloaded >= this.total) {
      this.timeOutId = null;
      this.status = this.STATUS.DOWNLOADED;
      setTimeout(this.onDownloadingFinished_.bind(this, this.channelId), 10);

      //this.peerCtrl_.closeChannel(this.channelId);
      return false;
    } else {
      this.drawDownloadProgress_(this.channelId);
      this.timeOutId = setTimeout(this.onDownloading.bind(this), this.interval);
      return true;
    }
  },

  /*
    callback functions begin
  */
  drawDownloadProgress_: function(channelId){
    /*if(!this.divId) return;
    var pd = $(this.divId);
    if(!pd) return;

    var boxCount = 20;
    var downCount = parseInt( this.downloaded / this.total * boxCount );
    var rate = downCount / boxCount * 100;
    var leftCount = boxCount - downCount;

    var progress = "";
    for(i=1; i <= downCount ; i++)
      progress += "<img src='images/downloaded.gif'>";
    for(i=1; i <= leftCount ; i++)
      progress += "<img src='images/left.gif'>";

    progress += "<a href='#' onclick='javascript: cancelProgress(\""+channelId+"\")'>cancel</a>";

    progress += "&nbsp;" + rate + "%";

    pd.innerHTML = progress;*/
  },

  onDownloadingFinished_: function(channelId){
    /*if(!this.divId){
      var ret = this.save();
      if(!ret){
        this.cancelDownload();
      }
      return;
    }

    var pd = $(this.divId);
    if(pd) 
      pd.innerHTML = "Ready";*/
  },

  onDownloadCanceled_: function(channelId){
    /*if(!this.divId){
      return;
    }

    var pd = $(this.divId);
    if(!pd) return;

    var download = "<a href='#' onclick='javascript: downloadFile(\""+channelId+"\", \""+this.fileName+"\");'>Download</a>";
    pd.innerHTML = download;*/
  },

  onNoAdapter_: function(){}
}

/*
*  @class: Rox.FileCenter
*
*  @brief: singleton class ,Control Center of all Rox.FileCtrl.
*
*  @example: see also Rox.FileCenter.instance
*/
Rox.FileCenter = Class.create();
Rox.FileCenter.prototype = {
  initialize: function(){
    this.fileCtrlList_ = new Array();
  },
  registerFileCtrl: function(fileCtrl){
    var cid = fileCtrl.channelId;
    if(!cid) return false;
    this.fileCtrlList_[cid] = fileCtrl;
    return true;
  },

/* see it just as a example please. how to use Rox.FileCtrl
  register: function(channelId, interval, fileName, divId){
    var fileCtrl = new Rox.FileCtrl();
    var ret = fileCtrl.init(channelId, interval, fileName, divId);
    if(!ret) return false;

    fileCtrl.start();
    this.fileCtrlList_[channelId] = fileCtrl;
    return true;
  },
*/
  cancelDownload: function(channelId){
    var fileCtrl = this.fileCtrlList_[channelId];
    if(fileCtrl) fileCtrl.cancelDownload();
    this.fileCtrlList_[channelId] = null;
  },

  getFileCtrl: function(channelId){
    var fileCtrl = this.fileCtrlList_[channelId];
    if(fileCtrl) 
      return fileCtrl;
    else 
      return null;
  },

  getStatus: function(channelId){
    var fileCtrl = this.fileCtrlList_[channelId];
    if(fileCtrl) return fileCtrl.getStatus();
    else return "Unknown";
  }
}

/*
*  @object: the sigleton of Rox.FileCenter.
*
*  @brief: we need one and only Rox.FileCenter to control all Rox.FileCtrl
*
*  @example: see also Rox.onSaveProgress

var fileCenter = Rox.FileCenter.instance();

function downloadFile(channelId, fileName){
  var interval = 2000; // interval to check download rate
  var fileCenter = Rox.FileCenter.instance();

  var fileCtrl = new Rox.FileCtrl();
  if(!fileCtrl.init(channelId, interval, fileName, "Down_"+channelId)) return false;
  fileCtrl.start();
  fileCenter.registerFileCtrl(fileCtrl);
  return true;
}
function cancelProgress(channelId){
  var fileCenter = Rox.FileCenter.instance();

  fileCenter.cancelDownload(channelId);
}
*******************
*  @deprecate: var xxxx = new Rox.FileCenter(); nor var kkkkkk = Rox.fileCenter_;
********************
*/
Rox.fileCenter_ = null;
Rox.FileCenter.instance = function(){
  if(!Rox.fileCenter_){
    Rox.fileCenter_ = new Rox.FileCenter();
  }
  return Rox.fileCenter_;
}
/*end of roxlib.js*/

/*part of mercury.js*/
if((typeof Rox == "undefined"))
  throw("Rox library(ad_roxlib.js) required!");

var Mercury = {
  Version: '2.0.0'
};

Mercury.EnsureAdapter = Class.create();
Mercury.EnsureAdapter.prototype = {
  initialize: function(){
    this.domain = '';
    this.errorReportUrl = '';
    this.adapterVersionArray = null;

    this.status = 'init';

    this.tcall_ = new Rox.TimeoutCall();
    this.peerCtrl_ = Rox.PeerCtrl.instance();
    this.tcall_.init(this.ensure_.bind(this), 10000);
  },
  init: function(domain, errorReportUrl, version){
    if(!domain)
      return false;
    this.domain = domain;
    this.errorReportUrl = errorReportUrl;

    if(version){
      version = String(version);
      var adapterVersionString = String(version.match(/\d+\.\d+\.\d+\.\d+/));
      var adapterVersionArray = adapterVersionString.split(".");
      this.adapterVersionArray = adapterVersionArray;
    }
    return true;
  },
  start: function(){
    if(this.status == 'ok')
      return;

    this.tcall_.start();
  },
  ensure: function(){
    if(this.status == 'ok')
      return;

    if(this.tcall_.act()){
      //alert("You have not installed Client successfully. Please reinstall or contact us.");
    }
  },
  ensure_: function(){
    var ret = this.peerCtrl_.init(this.domain, this.errorReportUrl, this.adapterVersionArray);
    if(1 == ret){
    }else if(-1 == ret){
      try{this.onAdapterInitFailed();}catch(e){};
      return false;
    }else if(-2 == ret){
      try{this.onAdapterNotInstalled();}catch(e){};
      return true;
    }else if(-3 == ret){
      alert("it is our fault, we use null parameters with mistake");
      return false;
    }else if(-4 == ret){
      try{this.onPeerStartFailed();}catch(e){};
      return false;
    }else{
      alert("Mercury.EnsureAdapter.ensure_(): peerCtrl.init() Unknown return value");
      return false;
    }
    ret = this.onAdapterWork();
    if(ret){
      this.status = 'ok';
      return false;
    }else return false;
  },
  onAdapterWork: function(){
    return true;
  },
  onAdapterInitFailed: function(){
  },
  onPeerStartFailed: function(){
  },
  onAdapterNotInstalled: function(){
  },
  endMember: function(){
  }
}

Mercury.QueryCurrentLoginHelper = Class.create();
Mercury.QueryCurrentLoginHelper.prototype = {
	initialize: function(){
		this.peerCtrl_ = Rox.PeerCtrl.instance();
		this.xmlParser_ = Rox.XmlParser.instance();

		this.user = '';
		this.domain = '';
		this.session_server = '';
	},
	init: function(){
		return this.xmlParser_.init();
	},
	query: function(){
		var rStr = this.peerCtrl_.queryCurrentLogin();
		//alert(rStr);
		if(rStr=="" || rStr=="login")
			return false;
		var xmlDoc = this.xmlParser_.loadXML(rStr);
		if(!xmlDoc)
			return false;
		var root = xmlDoc.getElementsByTagName("login")[0];
		if(!root)
			return false;
		this.user = root.getAttribute("user");
		this.domain = root.getAttribute("domain");
		this.session_server = root.getAttribute("session_server");
		return true;
	}
}

Mercury.LoginCtrl = Class.create();
Mercury.LoginCtrl.prototype = {
	initialize: function(){
    this.operationID = '';

		this.count = 10;
		this.u = '';
		this.p = '';
		this.ss = '';
		this.peerCtrl_ = Rox.PeerCtrl.instance();
		this.tcall_ = new Rox.TimeoutCall();
		this.tcall_.init(this.query_.bind(this), 1000);
		this.qCLogin_ = new Mercury.QueryCurrentLoginHelper();
	},
	login: function(u, p, ss){
		this.u = u;
		this.p = p;
		this.ss = ss;
    
		if(this.qCLogin_.query()){
			try{this.onLoginAlready(this.qCLogin_.user, this.qCLogin_.domain, this.qCLogin_.session_server);}catch(e){};
      return;
		}

		this.login_();
	},
  query_: function(){
   var ret = this.peerCtrl_.queryOperationStatus(this.operationID);
   //alert(ret);
   if(ret.indexOf("running") != -1){
      return true;
   }else if(ret.indexOf("error") != -1){
      this.operationID = '';
      try{this.onLoginFailed();}catch(e){};
      setTimeout(this.login_.bind(this), 1000);
      return false;
   }else if(ret.indexOf("completed") != -1){
      this.operationID = '';
      try{this.onLoginSuccess();}catch(e){};
      return false;
   }
  },
	login_: function(){
		this.count = this.count - 1;
		if(this.count<1) return false;

		if(this.count == 8){
			this.peerCtrl_.collectDiagnosticInformation(3);
      this.peerCtrl_.reportError();
		}

		try{this.onEachLogin();}catch(e){};
    //alert("login");
		var ret = this.peerCtrl_.login(this.u, this.p, this.ss);
    //alert(ret);
    if(ret == ""){
      try{this.onLoginFailed();}catch(e){};
      setTimeout(this.login_.bind(this), 10000);
      return;
		}
		this.operationID = ret;

    this.tcall_.start();
	},
	onLoginFailed: function(){
		alert("Login failed");
	},
	onEachLogin: function(){
	},
	onLoginAlready: function(u, d, ss){
	},
	onLoginSuccess: function(){
	}
}

Mercury.ThinSpeedComputer = Class.create();
Mercury.ThinSpeedComputer.prototype = {
  initialize: function(){
    this.currentSpeed = 0;
    this.lastD = 0;
    this.lastTime = 0;

    this.startTime = 0;
    this.startD = 0;
    this.averageSpeed = 0;
  },
  compute: function(downloaded){
    var date = new Date();
    var time = date.getTime();

    if(0 == this.lastTime){
      this.lastTime = time-1000;//don't change
      this.startTime = time-1;//don't change
      this.lastD = downloaded;
      this.startD = downloaded;
    }

if(downloaded > this.lastD){
    this.currentSpeed = (downloaded-this.lastD)/(time-this.lastTime)*1000;
    this.lastD = downloaded;
    this.lastTime = time;
}
    this.averageSpeed = (downloaded-this.startD)/(time-this.startTime)*1000;
  },
  reset: function(){
    this.currentSpeed = 0;
    this.lastD = 0;
    this.lastTime = 0;

    this.startTime = 0;
    this.startD = 0;
    this.averageSpeed = 0;
  }
}

Mercury.PeerStatus = Class.create();
Mercury.PeerStatus.prototype = {
  initialize: function(){
    this.peerCtrl_ = Rox.PeerCtrl.instance();
    this.xmlParser_ = Rox.XmlParser.instance();

    this.pieces = null;
    this.peers = null;
    this.servers = null;
  },
  init: function(){
    return this.xmlParser_.init();
  },

  status: function(cid){
    var rStr = this.peerCtrl_.status(cid);
    if(!rStr)
      return false;
    //alert(rStr);
    var xmlDoc = this.xmlParser_.loadXML(rStr);
    if(!xmlDoc)
      return false;

    this.pieces = xmlDoc.getElementsByTagName("pieces")[0];
    this.peers = xmlDoc.getElementsByTagName("peers")[0];
    this.servers = xmlDoc.getElementsByTagName("servers")[0];
    return true;
  },

  endMember: function(){
  }
}

Mercury.StatusCtrl = Class.create();
Mercury.StatusCtrl.prototype = {
  initialize: function(){
    this.cid = '';

    this.peerStatus_ = new Mercury.PeerStatus();
    this.peerTell_ = new Rox.PeerTell();
    this.tcall_ = new Rox.TimeoutCall();
    this.tcall_.init(this.status_.bind(this), 30000);
  },
  start: function(cid){
    this.cid = cid;

    this.tcall_.start();
  },
  setInterval: function(interval){
    this.tcall_.setInterval(interval);
  },
  status_: function(){
    if(this.peerStatus_.status(this.cid)){
      return this.onStatusCome(this.peerStatus_.pieces,
                this.peerStatus_.peers,
                this.peerStatus_.servers);
    }
    return true;
  },
  stop: function(){
    this.tcall_.stop();
  },
  onStatusCome: function(pieces, peers, servers){
    return true;
  },
  endMember: function(){
  }
}

Mercury.CheckPeer = Class.create();
Mercury.CheckPeer.prototype = {
  initialize: function(){
    this.peerCtrl_ = Rox.PeerCtrl.instance();
    this.tcall_ = new Rox.TimeoutCall();
    this.tcall_.init(this.check_.bind(this), 3000);
  },
  start: function(){
    this.tcall_.start();
  },
  check_: function(){
    if(this.peerCtrl_.isAvailable()){
      return true;
    }
    this.peerIsDead();
    return false;
  },
  stop: function(){
    this.tcall_.stop();
  },
  peerIsDead: function(){
  },
  endMember: function(){
  }
}
/*end  of rox.js  mercury*/
//classes end
/*begin of adelivery.js*/
if(typeof Mercury == "undefined")
  throw("Mercury library(ad_rox.js) required!");
/*
//you must define these functions below yourself.
//when page is onload, call Rox_initPage();
function Rox_UpdateAdapter(){
}
function Rox_InstallPeer(){
}
function Rox_UpdatePeer(){
}
function Rox_Work(){
}
function Rox_PeerIsDead(){
}
function Rox_InstallAdapter(){
}
function Rox_LoginFailed(){
}
function Rox_PeerStartFailed(){
}
*/
function Rox_PlayerSeekCallBack(time){
  Rox_playerCtrl.seek(time);
}
var Rox_playerCtrl = null;
var Rox_ensureAdapter = null;
var Rox_loginCtrl = null;
var Rox_checkPeer = null;
function Rox_checkVersion(){
  var peerCtrl = Rox.PeerCtrl.instance();

  if(peerCtrl.adapterVersionLow){    
    //peerCtrl.shutdown();
    peerCtrl.reset();
    
    try{setTimeout(Rox_UpdateAdapter, 0);}catch(e){};
    return false;
  }

  var peerVersionString = String(Rox_peerVersion.match(/\d+\.\d+\.\d+\.\d+/));
  var peerVersionArray = peerVersionString.split(".");

  var userPeerVersion = peerCtrl.getVersion();
  //alert(userPeerVersion);
  if(typeof(userPeerVersion) == "undefined" || userPeerVersion == null){
    try{setTimeout(Rox_UpdateAdapter, 0);}catch(e){};
    return false;
  }
  var userPeerVersionString = String(userPeerVersion.match(/\d+.\d+.\d+.\d+/));
  var userPeerVersionArray = userPeerVersionString.split(".");

  for(var i=0; i<4; i++){
    var pvi = parseInt(peerVersionArray[i]);
    var userpvi = parseInt(userPeerVersionArray[i]);
    if(pvi>userpvi){
      //peerCtrl.shutdown();
      peerCtrl.reset();
      try{setTimeout(Rox_UpdatePeer, 0);}catch(e){};
      return false;
    }else if(pvi<userpvi){
      break;
    }
  }
  setTimeout(Rox_login, 0);
  return true;
}
function Rox_login(){
  Rox_loginCtrl.login(Rox_u, Rox_p, Rox_ss);
}
function Rox_afterLogin(){
  Rox_checkPeer.start();
  Rox_Work();
}
var Rox_oldOnunload = null;
function Rox_onunload(){
  Rox_checkPeer.stop();
  Rox_playerCtrl.stop();
  var peerCtrl = Rox.PeerCtrl.instance();
  if(peerCtrl.isAvailable()){
    peerCtrl.closeAllChannels();
    peerCtrl.endSession();
    peerCtrl.reset();
  }
  if(typeof(Rox_oldOnunload) == "function"){
    Rox_oldOnunload();
  }
}
var Rox_initOnce = false;
function Rox_initPage(){
  if(Rox_initOnce) return;
  Rox_initOnce = true;

  if(Rox_disable){
    Rox_playerCtrl = new Rox.PlayCtrl_fake();
    Rox_Work();
    return;
  }

  Rox_ensureAdapter = new Mercury.EnsureAdapter();
  Rox_ensureAdapter.onAdapterWork = Rox_checkVersion;
  Rox_ensureAdapter.onAdapterInitFailed = Rox_UpdateAdapter;
  Rox_ensureAdapter.onPeerStartFailed = Rox_LoginFailed;
  if(typeof(Rox_PeerStartFailed) == "function"){
    Rox_ensureAdapter.onPeerStartFailed = Rox_PeerStartFailed;
  }
  Rox_ensureAdapter.onAdapterNotInstalled = Rox_InstallPeer;
  if(typeof(Rox_InstallAdapter) == "function"){
    Rox_ensureAdapter.onAdapterNotInstalled = Rox_InstallAdapter;
  }
  Rox_ensureAdapter.init(Rox_domain, Rox_errorReportUrl, Rox_adapterVersion);

  Rox_loginCtrl = new Mercury.LoginCtrl();
  Rox_loginCtrl.onEachLogin = function(){
    this.ss = Rox_getSS();
  }
  Rox_loginCtrl.onLoginAlready = Rox_afterLogin;
  Rox_loginCtrl.onLoginSuccess = Rox_afterLogin;
  if(typeof(Rox_LoginFailed) == "function"){
    Rox_loginCtrl.onLoginFailed = Rox_LoginFailed;
  }

  Rox_playerCtrl = new Rox.PlayCtrl2();

  Rox_checkPeer = new Mercury.CheckPeer();
  if(typeof(Rox_PeerIsDead) == "function"){
    Rox_checkPeer.peerIsDead = Rox_PeerIsDead;
  }

  Rox_oldOnunload = window.onunload;
  window.onunload = Rox_onunload;

  Rox_ensureAdapter.start();
}
/*end of adelivery.js*/
