/******************************************************************************

  rawflow.js - Common functions for Rawflow-enabled web broadcasts.

  Copyright (C) 2002-2005 Rawflow Limited

  $Id: rawflow.js,v 1.26 2006/06/09 16:38:57 danielf Exp $

 ******************************************************************************/

////////////////////////////// Global Variables ///////////////////////////////

var DEBUG               = false;
var PLUGINID            = "@rawflow.com/ICDClient,version="

var gClientMandatory    = false;
var gBrowserUnsupported = false;
var gFallbackUrl        = "";                                            // The URL to fall back to when something goes wrong.
var gShowCloseWindow	= false;											 // Should we show a warning message when closing the window
var gCloseWindowMessage = "Closing this window will end the broadcast."; // The message to display on close.
var gLoadingElement     = "";                                            // An element to show while the control is loading.
var gNotLoadingElement  = "";                                            // An element to show when the control has finished loading.
var gLoadingMovie       = "";                                            // A Flash movie to play while the control is loading.
var gNotLoadingMovie    = "";                                            // A Flash movie to play when the control has finished loading.
var gLoadingTimeout;                                                     // Used to delay a bit before showing the loading div.
var g_client;
var g_isSP2             = (window.navigator.userAgent.indexOf("SV1") != -1);
var playerheight		= 50;
var playerwidth			= 170;

////////////////////////////// Property Setters //////////////////////////////

function setFallbackUrl(url) {
  gFallbackUrl = url;
}

function setShowCloseWindow(show) {
  gShowCloseWindow = show;
}

function setCloseWindowMessage(message) {
  gCloseWindowMessage = message;
}

function setLoadingElement(element) {
  gLoadingElement = element;
}

function setNotLoadingElement(element) {
  gNotLoadingElement = element;
}

function setLoadingMovie(movie) {
  gLoadingMovie = movie;
}

function setNotLoadingMovie(movie) {
  gNotLoadingMovie = movie;
}

function setClientMandatory() {
  gClientMandatory = true;
}

////////////////////////////// Utility Functions //////////////////////////////

function debug(message) {
  if (DEBUG) {
    alert(message);
  }
}

function hasPlugin(plugin) {
  var result = false;
  if (navigator.plugins && navigator.plugins.length) {
    for(i = 0; i < navigator.plugins.length; i++) {
      if(navigator.plugins[i].name.indexOf(plugin) != -1) {
        result = true;
        break;
      }
    }
  }
  return result;
}

function hasActiveX() {
  // Annoyingly, window.ActiveXObject is defined on MacOS,
  // even though that OS can't load ActiveX objects!
  return (window.ActiveXObject && navigator.userAgent.indexOf('Win') != -1);
//         || (hasPlugin('ActiveX') && window.GeckoActiveXObject);
}

function tryExpression(expression) {
  var result = null;
  if(document.getElementById) {
    // Only later-generation browsers support try..catch
    eval('try { result = ' + expression + '; } catch (e) { }');
  } else {
    eval('result = ' + expression + ';');
  }
  return result;
}

function tryStatement(statement) {
  var result = false;
  debug('Trying ' + statement);
  if(document.getElementById) {
    // Only later-generation browsers support try..catch
    eval('try { ' + statement + '; result = true; } catch (e) { }');
  } else {
    eval('' + statement + '; result = true;');
  }
  return result;
}

function createActiveXObject(id) {
  var control = null;
  // Annoyingly, window.ActiveXObject is defined on MacOS,
  // even though that OS can't load ActiveX objects!
  if(window.ActiveXObject && navigator.userAgent.indexOf('Win') != -1) {
    control = tryExpression('new ActiveXObject("' + id + '")');
  } else if(hasPlugin('ActiveX') && window.GeckoActiveXObject) {
    control = tryExpression('new GeckoActiveXObject("' + id + '")');
  }
  return control;
}

function getFrame(frame) {
  var win = null;
  if(document.getElementById) {
    win = document.getElementById(frame);
  } else if(document.all) {
    win = document.all[frame];
  } else if(document.frames) {
    win = document.frames[frame];
  }
  return (win != null && win.contentWindow) ? win.contentWindow : win;
}

function frameNavigate(frame, url) {
  if(frame.location) {
    frame.location.href = url;
  } else if(frame.src) {
    frame.src = url;
  }
}

function show(layer) {
  if(document.getElementById) {
    document.getElementById(layer).style.visibility = "visible";
  } else if(document.all) {
    document.all[layer].style.visibility = "visible";
  } else if(document.layers) {
    document.layers[layer].visibility = "show";
  }
}

function hide(layer) {
  if(document.getElementById) {
    document.getElementById(layer).style.visibility = "hidden";
  } else if(document.all) {
    document.all[layer].style.visibility = "hidden";
  } else if(document.layers) {
    document.layers[layer].visibility = "hide";
  }
}

function getSearchVariable(name) {
  var startchar = location.search.indexOf("" + name + "=", 1) + name.length + 1;
  if ((startchar - name.length - 1) < 0) {
    return "";
  }
  var endchar = location.search.indexOf('&', startchar)
  if(endchar < 0) {
    endchar = location.search.length;
  }
  return location.search.substring(startchar, endchar);
}

function isMac() {
  return (navigator.userAgent.indexOf('Mac') != -1);
}

////////////////////////////// Private Functions //////////////////////////////

function _startLoading() {
  if(gLoadingElement != "") {
    show(gLoadingElement);
  }
  if(gNotLoadingElement != "") {
    hide(gNotLoadingElement);
  }
  if(gLoadingMovie != "" && document[gLoadingMovie]) {
    document[gLoadingMovie].Play();
  }
  if(gNotLoadingMovie != "" && document[gNotLoadingMovie]) {
    document[gNotLoadingMovie].Stop();
  }
}

function _stopLoading() {
  if(gLoadingElement != "") {
    hide(gLoadingElement);
  }
  if(gNotLoadingElement != "") {
    show(gNotLoadingElement);
  }
  if(gLoadingMovie != "" && document[gLoadingMovie]) {
    document[gLoadingMovie].Stop();
  }
  if(gNotLoadingMovie != "" && document[gNotLoadingMovie]) {
    document[gNotLoadingMovie].Play();
  }
}

//
// Wait (using setTimeout) for client to be ready before trying to call play()
// Allows users to not think that their browser has 'crashed' while waiting for
// client to talk to server.
//
function _waitAndPlay() {
  if(g_client.canPlay()) {
    stopLoading();
    window.onbeforeunload = closeWindow;
    g_client.play();
  } else {
    // timeout in ms - as fine grained as necessary.
    setTimeout("_waitAndPlay()", 200);
  }
}

////////////////////////////// Public Functions ///////////////////////////////

function fallback(player) {
  if(gFallbackUrl != "") {
    if(player == null) {
      debug('no player - falling back to ' + gFallbackUrl);
      location.href = gFallbackUrl;
    } else {
      player.play(gFallbackUrl);
    }
  }
  stopLoading();
}

function start(client, player) {
  if(client == null) {
    if(gBrowserUnsupported || !gClientMandatory) {
      fallback(player);
    } else {
      stopLoading();
    }
  } else {
    client.setPlayer(player);
    debug('calling client.start()');
    client.start();
    if(client.isRunning()) {
      debug('waiting for control to be ready');
      g_client = client;
      _waitAndPlay();
    } else if(!gClientMandatory) {
      fallback(player);
    } else {
      debug('stop Loading');
      stopLoading();
    }
  }
}

function closeWindow() {
  if(gShowCloseWindow) {
    // Display a message if the user tries to close the window.
    return gCloseWindowMessage;
  }
}

function startLoading() {
  gLoadingTimeout = setTimeout(_startLoading, 500);
}

function stopLoading() {
  clearTimeout(gLoadingTimeout);
  _stopLoading();
}

//////////////////////////////// Media Players ////////////////////////////////

function ActiveXWindowsMediaPlayer(playerName, width, height) {
  this.playerName = playerName;
  this.width = width;
  this.height = height;

  this.player = null;
  this.playing = false;

  this.output = function() {
    document.writeln('<object id="' + this.playerName + '" ');
    document.writeln('        classid="CLSID:22d6f312-b0f6-11d0-94ab-0080c74c7e95" ');
    document.writeln('        codebase="http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=5,1,52,701" ');
    document.writeln('        standby="Loading Microsoft Windows Media Player components..." ');
    document.writeln('        type="application/x-oleobject" ');
    document.writeln('        width="' + this.width + '" ');
    document.writeln('        height="' + this.height + '">');
    document.writeln('  <param name="AnimationatStart" value="false"/>');
    document.writeln('  <param name="TransparentatStart" value="true"/>');
    document.writeln('  <param name="AutoStart" value="true"/>');
    document.writeln('  <param name="ShowControls" value="true"/>');
    document.writeln('  <param name="ShowAudioControls" value="true"/>');
    document.writeln('  <param name="ShowPositionControls" value="false"/>');
    document.writeln('  <param name="ShowTracker" value="false"/>');
    document.writeln('  <param name="ShowDisplay" value="false"/>');
    document.writeln('  <param name="ShowCaptioning" value="false"/>');
    document.writeln('  <param name="ShowGotoBar" value="false"/>');
    document.writeln('  <param name="ShowStatusBar" value="true"/>');
    document.writeln('</object>');

    this.player = document[this.playerName];
    return this.player != null;
  }

  this.play = function(url) {
    if(this.player == null) {
      // Try to attach to an existing media player
      this.player = document[this.playerName];
    }
    if(this.player != null) {
      this.player.fileName = url;
      this.player.play();
      this.playing = true;
    }
  }

  this.isPlaying = function() {
    return this.playing;
  }
}

function FramedWindowsMediaPlayer(playerName, width, height) {
  this.playerName = playerName;
  this.width = width;
  this.height = height;

  this.player = null;
  this.playing = false;
  this.playerUrl = "mediaplayer.html";

  this.output = function() {
    document.writeln('<iframe id="' + this.playerName + '" name="' + this.playerName + '" ');
    document.writeln('        style="width: ' + this.width + 'px; height: ' + this.height + 'px; border: none" ');
    document.writeln('        frameborder="0" ');
    document.writeln('        src="' + this.playerUrl + '?width=' + this.width + '&height=' + this.height + '">');
    document.writeln('</iframe>');

    this.player = getFrame(this.playerName);
    return this.player != null;
  }

  this.play = function(url) {
    if(this.player == null) {
      // Try to attach to an existing media player
      this.player = getFrame(this.playerName);
    }
    if(this.player != null) {
      var src = this.playerUrl + "?url=" + escape(url)
                                         + "&width=" + this.width
                                         + "&height=" + this.height;
      frameNavigate(this.player, src);
      this.playing = true;
    }
  }

  this.isPlaying = function() {
    return this.playing;
  }

  this.setPlayerUrl = function(url) {
    this.playerUrl = url;
  }
}

/////////////////////////////// Rawflow Clients ///////////////////////////////

function ActiveXRawflowClient(clientName, version, path) {
  this.clientName = clientName;
  versionArray = version.split(".");
  this.version = versionArray.join(",");
  this.path = path;

  this.rawflow = null;
  this.player = null;
  this.modified = true;
  this.worked = false;
  this.properties = new Object();
  this.stunservers = new Array();

  this.requiresInstall = function() {
    return false;
  }

  this.install = function() {
  }

  this.isValid = function() {
    return this.rawflow != null;
  }

  this.output = function() {
    document.writeln('<object id="' + this.clientName + '" width="100" height="100" '); 
    document.writeln('        classid="CLSID:029FDBA6-3547-11D7-AA4C-0050BF051A00" ');
//    document.writeln('        classid="CLSID:F9E0DAF4-7AA7-45AC-93CF-E5BD69B1CE93" ');
    document.writeln('        codebase="' + this.path + 'Rawflow.cab#Version=' + this.version + '">');
    document.writeln('</object>');

    this.rawflow = document[this.clientName];
    return this.isValid();
  }

  this.start = function() {
    if(this.rawflow == null || createActiveXObject("RFACTIVEX.RawflowCtrl.1") == null) {
      return false;
    }

    this.setProperty("Embedded", (this.player != null));

    for(var property in this.properties) {
      this.rawflow[property] = this.properties[property];
    }

    if(this.modified) {
      this.modified = false;
      this.worked = true;
      for (var serverindex = 0; serverindex < this.stunservers.length; ++serverindex) {
        stunServerName = this.stunservers[serverindex];
        this.worked = this.worked && tryStatement("this.rawflow.addStunServer('" + stunServerName + "', 3478)");
      }
      this.worked = this.worked && tryStatement("this.rawflow.start()");
    } else {
      this.worked = tryStatement("this.rawflow.restart()");
    }
  }


  this.isRunning = function() {
    return this.worked;
  }

  this.canPlay = function() {
    return this.rawflow.TempFileReady;
  }

  this.play = function() {
    if(this.player != null) {
      this.player.play(this.rawflow.TempFileName);
    }
  }

  this.setConfig = function(config) {
  }

  this.setProperty = function(name, value) {
    this.modified = (this.properties[name] != value);
    this.properties[name] = value;
  }

  this.setPlayer = function(player) {
    this.player = player;
  }

  this.addStunServer = function(server) {
    this.stunservers[this.stunservers.length] = server;
    this.modified = true;
  }

  // Add a trailing slash to the path if one does not exist, but retain empty paths
  if(this.path != "" && this.path.charAt(this.path.length - 1) != "/") {
    this.path += "/";
  }
}

function PluginRawflowClient(clientName, version, path) {
  this.clientName = clientName;
  this.version = version;
  this.path = path;

  this.config = "";
  this.client = "";
  this.rawflow = null;
  this.player = null;
  this.started = false;
  this.worked = false;
  this.installed = false;

  this.callBack = function(url, status) {
    installed = (status == 0);
  }

  this.requiresInstall = function() {
    return ("undefined" != typeof(InstallTrigger)) && InstallTrigger.compareVersion(PLUGINID + this.version, this.version) < 0;
  }

  this.install = function() {
    if(this.requiresInstall() && !this.installed) {
      // XPInstall
      if(this.client != "") {
        InstallTrigger.install( { "Rawflow Client Plugin" : this.client }, this.callBack );
      }
    }
  }

  this.isValid = function() {
    return hasPlugin("Rawflow") && this.rawflow != null;
  }

  this.output = function() {
    this.install();
    document.writeln('<object id="' + this.clientName + '" ');
    document.writeln('        data="' + this.config + '" ');
    document.writeln('        codebase="' + this.client + '" ');
    document.writeln('        type="application/x-rawflow-stream" ');
    document.writeln('        width="0" ');
    document.writeln('        height="0">');
    document.writeln('</object>');

    this.rawflow = document[this.clientName];
    return this.isValid();
  }

  this.start = function() {
    this.worked = hasPlugin("Rawflow") && this.rawflow != null;
  }

  this.isRunning = function() {
    return this.worked;
  }

  this.canPlay = function() {
    return true;
  }

  this.play = function() {
  }

  this.setConfig = function(config) {
    this.config = config;
  }

  this.setProperty = function(name, value) {
  }

  this.setPlayer = function(player) {
    this.player = player;
  }

  if(this.path == "") {
    // If the path is empty, use the current page's path.
    this.path = location.href.substring(0, location.href.lastIndexOf('/') + 1);
  } else if(this.path.charAt(this.path.length - 1) != "/") {
    // Add a trailing slash to the path if one does not exist, but retain empty paths
    this.path += "/";
  }
  if(navigator.userAgent.indexOf('Windows') >= 0) {
    this.client = this.path + "rfwin.xpi";
  } else if(navigator.userAgent.indexOf('Mac') >= 0) {
    this.client = this.path + "rfmac.xpi";
  } else if(navigator.userAgent.indexOf('Linux') >= 0) {
    this.client = this.path + "rflinux.xpi";
  }
}

function JavaWebStartRawflowClient(clientName, version, path) {
  this.clientName = clientName;
  this.version = version;
  this.path = path;

  this.worked = false;
  this.player = null;

  this.isValid = function() {
    return true;
  }

  this.output = function() {
    return true;
  }

  this.start = function() {
    this.worked = true;
  }

  this.isRunning = function() {
    return this.worked;
  }

  this.canPlay = function() {
    return true;
  }

  this.play = function() {
  }

  this.setProperty = function(name, value) {
  }

  this.setPlayer = function(player) {
    this.player = player;
  }
}

function FramedRawflowClient(frameName, clientUrl) {
  this.frameName = frameName;
  this.clientUrl = clientUrl;

  this.config = "";
  this.rawflow = null;
  this.worked = false;
  this.player = null;
  this.properties = new Object();

  this.requiresInstall = function() {
    return false;
  }

  this.install = function() {
  }

  this.output = function() {
    document.writeln('<iframe id="' + this.frameName + '" name="' + this.frameName + '" ');
    document.writeln('        style="width: 0px; height: 0px; border: none; position:absolute" ');
    document.writeln('        frameborder="0" ');
    document.writeln('        src="' + this.clientUrl + '?config=' + escape(this.config) + '">');
    document.writeln('</iframe>');

    this.rawflow = getFrame(this.frameName);
    return this.rawflow != null;
  }

  this.start = function() {
    if(this.rawflow == null) {
      return false;
    }

    frameNavigate(this.rawflow, this.clientUrl + "?config=" + escape(this.config));

    for(var property in this.properties) {
      this.rawflow.getClient().setProperty(property, this.properties[property]);
    }

    this.rawflow.getClient().setPlayer(this.player);

    this.worked = this.rawflow.getClient().start();
  }

  this.isRunning = function() {
    return this.worked;
  }

  this.setConfig = function(config) {
    this.config = config;
  }

  this.setProperty = function(name, value) {
    this.properties[name] = value;
  }

  this.setPlayer = function(player) {
    this.player = player;
  }
}

////////////////////////////////// Factories //////////////////////////////////

function createWindowsMediaPlayer(width, height) {
  var player = null;
  if(createActiveXObject("MediaPlayer.MediaPlayer.1") != null) {
    player = new ActiveXWindowsMediaPlayer("player", width, height);
  } else if(hasPlugin("Windows Media")) {
    player = new FramedWindowsMediaPlayer("player", width, height);
  }
  if(player != null && !player.output()) {
    player = null;
  }
  return player;
}

function createMp3MediaPlayer(width, height) {
  var player = null;
  if (!isMac()) {
    player = createWindowsMediaPlayer(width, height);
  } else {
    debug('Mac being used');
  }
  return player;
}

function createRawflowClient(version, path, config) {
  var rawflow = null;
  if(hasActiveX()) {
    rawflow = new ActiveXRawflowClient("rawflow", version, path);
  } else if(isMac()) {
//    rawflow = new JavaWebStartClient("rawflow", version, path);
  } else if(navigator.plugins) {
//    rawflow = new PluginRawflowClient("rawflow", version, path);
  }
  if(rawflow == null) {
    gBrowserUnsupported = true;
  } else {
    rawflow.setConfig(config);
    rawflow.output();
  }
  return rawflow;
}

function createFramedRawflowClient(clientUrl) {
  var rawflow = new FramedRawflowClient("rawflow", clientUrl);
  if(!rawflow.output()) {
    rawflow = null;
  }
  return rawflow;
}

///////////////////////////////////////////////////////////////////////////////



// from player.js

// Change this to make the trial optional or compulsory.
var requiresConfirm = true;

var confirmUrl = "dialog2.html";
var contentUrl = "player2.asp";

var bHasLoadedRawflow = false;

//////////////////////////////////////////////////////////////////////////////
// Cookie Functions
// save/read/delete cookie functions for storing small chunks of data in the browser
// 19990326

// Copyright (C) 1999 Dan Steinman
// Distributed under the terms of the GNU Library General Public License
// Available at http://www.dansteinman.com/dynapi/

// thanks to: Jesee Chisholm <JCHISHOLM@SENSORMATIC-VPD.com>
//////////////////////////////////////////////////////////////////////////////

function saveCookie(name,value) {
  var domain = "";
  if (domain != "")
    domain = "; domain="+domain;

  var days = 365;
  if (days) {
    var date = new Date();
    date.setTime(date.getTime()+(days*24*60*60*1000));
    var expires = "; expires="+date.toGMTString();
  }
  else
    expires = "";

  document.cookie = name+"="+value+expires+domain+"; path=/";
}

function readCookie(name) {
  var nameEQ = name + "=";
  var ca = document.cookie.split(';');
  for(var i=0;i<ca.length;i++) {
    var c = ca[i];
    while (c.charAt(0)==' ')
      c = c.substring(1,c.length);
    if (c.indexOf(nameEQ) == 0)
      return c.substring(nameEQ.length,c.length);
  }
  return "";
}

function deleteCookie(name) {
  saveCookie(name,"",-1);
}

//////////////////////////////////////////////////////////////////////////////

function getVariable(name) {
  var result = getSearchVariable(name);
  if(result == "") {
    result = readCookie(name);
  }
  return result;
}

var dialogue = requiresConfirm && getVariable("participant") == "";
var participant = !requiresConfirm || getVariable("participant") == "yes";

function doInitialCheck() {
  // Display the confirm dialogue if necessary.
  if(dialogue) {
    location.replace(confirmUrl + location.search);
  }
}

doInitialCheck();

function doStart(client, player) {
  start(client, player);

  if((client == null || !client.isRunning()) && (player == null || !player.isPlaying())) {
    // If something prevented us from starting, delete the cookie so the confirm dialogue will display again next time.
    //deleteCookie("participant");

  } else if(client != null && client.isRunning()) {
    // Re-instate the cookie in case it was deleted by SP2 blocking the control.
    saveCookie("participant", "yes");
  }
}

