// Implement missing IE functionality
if (Array.prototype.push == null)
   Array.prototype.push = function(){for(var i=0;i<=arguments.length;i++)this[this.length]=arguments[i]};
if (Array.prototype.join == null)
   Array.prototype.join = function(sep){var str=""+this[0];for(var i=1;i<=this.length;i++)str+=sep+this[i];return str};

function MLClass()
{
   this.maxslidedefaulturl = "MediaLandscape_maxslide.swf";
   this.maxslidewin = null;
   this.connkey = null;
   this.helpwidth = 437;
   this.helpheight = 400;
   this.helpdefaulturl = "help.html";
   this.homepagedefaulturl = "http://www.media-landscape.com/";
   this.htmlsocketname = null;
   this.pendinghtml = [];
   this.playerdefaulturl = "MediaLandscape_player.swf";
   this.configdefaulturl = "config.xml";
   this.viewerdefaulturl = "viewer.html";
   this.useWmode = false;
   this.flashProxy = null;

   this.templates = {
      toc: {
         indent: 8, // pixels of indent per TOC level
         url: "skin/template_toc.html",
         width: 300,
         height: 400
      },
      resources: {
         url: "skin/template_resources.html",
         width: 200,
         height: 200
      },
      slides: {
         url: "skin/template_slide.html",
         width: 550,
         height: 450
      }
   };

   this.targets = {};

   window.receiveCall = function(sockname, fn)
   {
      arguments.callee.context.setSocketName(sockname);
      // this will be called with wrong context, so 'this' cannot be used.
      //arguments.shift(); // you can't do this, so we fake it, below.
      var newargs = [];
      for(var i=2; i<arguments.length; i++)
      {
         newargs.push(arguments[i]);
      }
      //alert("receive "+fn+","+newargs);
      arguments.callee.context[fn].apply(arguments.callee.context, newargs);
   }
   window.receiveCall.context = this;
}

MLClass.prototype.buildPlayer = function(w, h, vars)
{
   var width = w == null ? 800 : w;
   var height = h == null ? 550 : h;
   if (vars == null)
      vars = {};
   if (vars.configURL == null)
      vars.configURL = this.configdefaulturl;

   // Get Flash arguments from HTML url
   this.extractUrlVars(""+window.location, vars);

   // Width and height are a special case
   if (vars.width != null)
   {
      width = vars.width;
      delete vars.width;
   }
   if (vars.height != null)
   {
      height = vars.height;
      delete vars.height;
   }

   var extra = "";
   if (document.getElementById("frameholder") == null)
      extra += '<div id="frameholder" style="position:absolute;top:0;left:0"></div>';
   if (document.getElementById("MLClassPFrame_iframe_asfunction") == null)
      extra += '<iframe id="MLClassPFrame_iframe_asfunction" style="position:absolute;left:-1000px;border-style:none" src=""></iframe>';

   return this.buildFlash(vars, width, height, this.playerdefaulturl) + extra;
}

MLClass.prototype.varsToQuery = function(vars)
{
   var params = [];
   for (var field in vars)
      if (field != "target")
         params.push(field+"="+escape(vars[field]));
   return params.join("&");
}
MLClass.prototype.varsToUrl = function(url,vars,query)
{
   if (query == null)
      query = this.varsToQuery(vars);
   if (query != "")
      url += "?" + query;
   if (vars.target != null)
      url += "#" + vars.target;
   return url;   
}

MLClass.prototype.buildFlash = function(vars, width, height, url)
{
   // This is redundant for the player, but not for the maxslide
   url = this.extractUrlVars(url, vars);

   var flashvars = this.varsToQuery(vars);
   url = this.varsToUrl(url,vars,flashvars);

   var ft = new FlashTag(url, width, height, "7,0,0,0");
   ft.setBgcolor("#FFFFFF");
   ft.setQuality("best");
   ft.setSalign("tl");
   if (this.useWmode)
      ft.setWmode("transparent");
   return ft.toString();
}
MLClass.prototype.showFlash = function(doc, vars, width, height, url)
{
   doc.write(this.buildFlash(vars, width, height, url));
}

MLClass.prototype.showHomePage = function(url)
{
   if (url == null || url == "")
      url = this.homepagedefaulturl;
   window.open(url);
}
MLClass.prototype.showMaxSlide = function(w, h, key, url)
{
   if (url == null || url == "")
      url = this.maxslidedefaulturl;
   if (this.maxslidewin == null || this.maxslidewin.document == null ||
       key != this.connkey)
   {
      this.connkey = key;
      var v = {
         maxSlideKey: key
      };
      this.maxslidewin = window.open("", "maxslide_"+key, 
                                     "width="+(w+50)+",height="+(h+50)+","+
                                     "menubar=no,directories=no,location=no,toolbar=no,status=no");
      var d = this.maxslidewin.document;
      d.open();
      d.write('<'+'html><'+'head>');
      d.write('<'+'title>Full-Size Slide</'+'title>');
      d.write('<'+'scr'+'ipt>window.ml={closeApp: function(){window.opener.ml.hideMaxSlide('+key+');}};</'+'scr'+'ipt>');
      d.write('</'+'head><'+'body onUnload="window.ml.closeApp()">');
      this.showFlash(d, v, w, h, url);
      d.write('</'+'body></'+'html>');
      d.close();
   }
}
MLClass.prototype.hideMaxSlide = function(key)
{
   if (this.maxslidewin != null && this.maxslidewin.document != null &&
       this.connkey == key)
   {
      this.maxslidewin.close();
      this.maxslidewin = null;
   }
}
MLClass.prototype.cleanup = function()
{
   this.hideMaxSlide(this.connkey);
   for (var name in this.targets)
      if (this.targets[name] != null && this.targets[name].close != null)
         this.targets[name].close();
}
MLClass.prototype.closeApp = function(errmsg)
{
   if (window.closing == true)
      return;
   this.cleanup();
   if (errmsg == null)
      errmsg = "";
   else
      errmsg = "'" + errmsg.split("'").join("\'") + "'";
   setTimeout("window.ml.closeAppFailed("+errmsg+")", 1500);
   window.close();
}
MLClass.prototype.closeAppFailed = function(msg)
{
   var langs = {
      en: "Your browser's security features have blocked the Close button.  You may close the browser window normally."
   };
   if (msg == null || msg == "")
      msg = "en";
   if (langs[msg] != null)
      msg = langs[msg];
   alert(msg);
         
}
MLClass.prototype.showHelp = function(url)
{
   if (url == null || url == "")
      url = this.helpdefaulturl
   window.open(url, "_blank", "width="+this.helpwidth+",height="+this.helpheight+","+
               "menubar=no,directories=no,location=no,toolbar=no,status=no,scrollbars=yes");
}
MLClass.prototype.resizeFlash = function(w,h,url)
{
   if (w > 0 && h > 0)
   {
      var list = this.findFlash(url);
      for (var i=0; i<list.length; i++)
      {
         list[i].obj.setAttribute("width", w);
         list[i].obj.setAttribute("height", h);
         list[i].embed.setAttribute("width", w);
         list[i].embed.setAttribute("height", h);
         list[i].obj.style.width = ""+w+"px";
         list[i].obj.style.height = ""+h+"px";
         list[i].embed.style.width = ""+w+"px";
         list[i].embed.style.height = ""+h+"px";
         //alert("is: "+[list[i].obj.style.width, list[i].obj.style.height, list[i].embed.style.width, list[i].embed.style.height]);
      }
   }
}

MLClass.prototype.rePlaceContent = function(idx)
{
   var args = this.pendinghtml[idx];
   this.pendinghtml[idx] = null;
   this.placeContent.apply(null, args);
}
MLClass.prototype.placeContent = function(html, type, style, x, y, w, h)
{
   if (style == null)
      style = "div";
   var el;
   var framename = "MLClassPFrame_"+style+"_"+type;
   if (style == "win")
   {
      if (w == null || w <= 0)
         w = 300;
      if (h == null || h <= 0)
         h = 300;
      el = window.open("", framename, "width="+(w+50)+",height="+(h+50)+","+
                       "menubar=no,directories=no,location=no,toolbar=no,status=no,scrollbars=yes");
   }
   else
   {
      el = document.getElementById(framename);
      if (el == null)
      {
         var holder = document.getElementById("frameholder");
         if (holder == null)
         {
            // Bad news... This reflows the whole page, killing flash
            holder = document.createElement("div");
            holder.style.display = "none";
            var body = document.getElementsByTagName("body")[0];
            body.appendChild(holder);
         }
         if (holder != null)
         {
            //var stylestr = "position:absolute;z-index:1;border:1px solid black;background-color:white";
            var stylestr = "position:absolute;z-index:100";
            if (style == "div")
            {
               holder.innerHTML += '<div id="'+framename+'" style="'+stylestr+'"></div>';
            }
            else if (style == "iframe")
            {
               holder.innerHTML += '<iframe id="'+framename+'" style="'+stylestr+'"></iframe>';
            }
            el = document.getElementById(framename);
         }
         if (style == "iframe" && el != null && el.document == null)
         {
            this.pendinghtml[this.pendinghtml.length] = arguments;
            setTimeout("window.ml.rePlaceContent("+(this.pendinghtml.length-1)+")", 100);
            return;
         }
      }
   }

   if (el != null)
   {
      // Replace all "asfunction:foobar" with "javascript:asfunction('foobar')"
      // The argument text (the 'foobar' in the example) must not contain ' or " or \ .
      var parts = html.split("asfunction:");
      for (var i=1; i<parts.length; i++)
      {
         var pos = parts[i].indexOf("\"");
         if (pos < 0)
            pos = 0;
         parts[i] = "javascript:window.ml.asfunction('" +
                    parts[i].substring(0,pos)
                            .split("'").join("")
                            .split("\"").join("")
                            .split("\\").join("") +
                    "')" + parts[i].substring(pos);
      }
      html = parts.join("");

      var d = el.document;
      if (d == null)
         d = el.contentDocument;
      if (d != null)
      {
         d.open();
         d.write('<html><body><div id="'+framename+"div"+'"></div></body></html>');
         d.close();
         el = d.getElementById(framename+"div");
      }
      el.innerHTML = html;
      if (x != null)
         el.style.marginLeft = ""+x+"px";
      if (y != null)
         el.style.marginTop = ""+y+"px";
      if (w != null)
         el.style.width = ""+w+"px";
      if (h != null)
         el.style.height = ""+h+"px";
   }
}
MLClass.prototype.asfunction = function(fn)
{
   var args;
   if (fn.indexOf(",") >= 0)
   {
      args = fn.split(",");
   }
   else
   {
      // Get a real array
      args = [];
      for (var i=0;i<arguments.length;i++)
         args[i] = arguments[i];
   }
   if (this.flashProxy == null)
   {
      this.flashProxy = new FlashProxy(this.htmlsocketname, "js/JavaScriptFlashGateway.swf");
   }
   //alert("asfunction "+args.length+" - "+args);
   this.flashProxy.call.apply(this.flashProxy, args);
}

MLClass.prototype.setSocketName = function(sockname)
{
   //alert("sock "+sockname);
   this.htmlsocketname = sockname;
}

MLClass.prototype.setWmode = function()
{
   if (!this.useWmode)
   {
      this.useWmode = true;
      var list = this.findFlash();
      for (var i=0; i<list.length; i++)
      {
         var params = list[i].obj.getElementsByTagName("param");
         for (var j=0; j<params.length; j++)
            if (params[j].getAttribute("name") == "wmode")
               params[j].setAttribute("value", "transparent");
         list[i].embed.setAttribute("wmode", "transparent");

         // Refresh the Flash (unfortunately necessary...)
         list[i].obj.innerHTML = list[i].obj.innerHTML;
      }
   }
}

MLClass.prototype.findFlash = function(url)
{
   var result = [];
   var objects = document.getElementsByTagName("object");
   for (var i=0; i<objects.length; i++)
   {
      var embeds = objects[i].getElementsByTagName("embed");
      if (embeds.length > 0 && (url == null || embeds[0].getAttribute("src") == url))
      {
         result[result.length] = {obj: objects[i], embed: embeds[0]};
      }
   }
   return result;
}

MLClass.prototype.extractUrlVars = function(url, vars)
{
   var j = url.indexOf("#");
   if (j >= 0)
   {
      var target = url.substring(j+1);
      if (target != "")
      {
         /*
         if (target.indexOf("=") >= 0)
         {
            var parts = target.split("&");
            for (var i=0; i<parts.length; i++)
            {
               var kv = parts[i].split("=");
               if (kv.length == 2 && kv[0].length > 0)
                  vars[kv[0]] = unescape(kv[1]);
            }
         }
         else
         */
            vars.target = target;
      }
      url = url.substring(0,j);
   }

   var i = url.indexOf("?");
   if (i > 0)
   {
      var query = url.substring(i+1);
      url = url.substring(0,i);
      if (query != "")
      {
         var parts = query.split("&");
         for (var i=0; i<parts.length; i++)
         {
            var kv = parts[i].split("=");
            if (kv.length == 2 && kv[0].length > 0)
               vars[kv[0]] = unescape(kv[1]);
         }
      }
   }
   return url;
}

MLClass.prototype.setTOC = function(targets, items)
{
   this.openTemplates(targets, items, "toc");
}
MLClass.prototype.setResources = function(targets, items)
{
   this.openTemplates(targets, items, "resources");
}
MLClass.prototype.setSlides = function(targets, items)
{
   this.openTemplates(targets, items, "slides");
}
MLClass.prototype.openTemplates = function(targets, items, type)
{
   var tmpl = this.templates[type];
   tmpl.data = items;
   var wasnull = false;
   for (var i=0; i<targets.length; i++)
   {
      var url = tmpl.url;
      if (this.targets[targets[i]] == null)
          wasnull = true;
      var el = document.getElementById(targets[i]);
      if (el != null && el.nodeName.toLowerCase() == "iframe")
      {
         this.targets[targets[i]] = el;
         // Workaround for odd Safari 1.3/2.0 bug
         el.src = "about:blank";
         el.src = url;
      }
      else
      {
         this.targets[targets[i]] = window.open(url, "MLP_extwin_"+type+"_"+targets[i],
                                                "width="+tmpl.width+",height="+tmpl.height+","+
                                                "menubar=no,directories=no,location=no,toolbar=no,status=no,scrollbars=yes");
      }
      if (this.targets[targets[i]] == null && this.popblockmsg == null)
      {
         this.popblockmsg = true;
         alert("Failed to open a new window.  To experience the full presentation, please disable popup blocking for this web address.");
      }
   }
   if (wasnull)
      window.focus();
}
// This is used for TOC, Resources and Slides
MLClass.prototype.fillTmpl = function(doc, type)
{
   var items = this.templates[type].data;
   if (doc != null)
   {
      var tmplNode = doc.getElementById("template");
      var tmpl = tmplNode.innerHTML;
      var out = "";
      for (var i=0; i<items.length; i++)
      {
         var item = items[i];
         var content = tmpl;

         if (type == "toc")
         {
            // TOC-specific tweaks
            var indent = item.level * this.templates.toc.indent;
            content = content.split('style=""').join('style="padding-left: '+indent+' px"');
            item.action = "javascript:window.ml.gotoID('"+item.id+"')";
            item.current = item.current ? "current" : "";
         }
         else if (type == "resources")
         {
            // Resource-specific tweaks
            item.action = "javascript:window.ml.clickrsrc('"+item.location+"',"+(item.pausePlayback?"'pause'":"'nopause'")+","+(item.newWindow?"'newwin'":"'thiswin'")+")";
         }
         else if (type == "slides")
         {
            // Slide-specific tweaks
            item.actionPrevious = "javascript:window.ml.prevSlide()";
            item.actionNext = "javascript:window.ml.nextSlide()";
         }

         for (var prop in item)
            content = content.split("${"+prop+"}").join(item[prop])
                             .split("$%7B"+prop+"%7D").join(item[prop]);
         out += content;
      }
      tmplNode.innerHTML = out;
      tmplNode.style.display = "";
   }
}

MLClass.prototype.gotoID = function(id)
{
   this.asfunction("gotoID", id);
}
MLClass.prototype.prevSlide = function()
{
   this.asfunction("prevSlide");
}
MLClass.prototype.nextSlide = function()
{
   this.asfunction("nextSlide");
}
MLClass.prototype.clickrsrc = function(url,stoppres,newwin)
{
   if (newwin=="newwin")
   {
      if (stoppres=="pause")
         this.asfunction("stopPresentation");
      window.open(url, "_blank");
   }
   else
   {
      window.closing = true;
      window.location = url;
   }
}

MLClass.prototype.nextSlide = function()
{
   this.asfunction("nextSlide");
}

MLClass.prototype.prevSlide = function()
{
   this.asfunction("prevSlide");
}

MLClass.prototype.launchViewer = function(dir,url,w,h,vars)
{
   var width = w == null ? 800 : w;
   var height = h == null ? 550 : h;
   if (vars == null)
      vars = {};

   if (url == null)
      url = this.viewerdefaulturl;
   if (dir != null)
      url = dir+"/"+url;

   this.extractUrlVars(""+window.location, vars);
   url = this.varsToUrl(url,vars);

   if (vars.width != null)
      width = vars.width;
   if (vars.height != null)
      height = vars.height;

   window.open(url, "_blank", "width="+width+",height="+height+","+
               "menubar=no,directories=no,location=no,toolbar=no,status=no,resizable=no,scrollbars=no,personalbar=no")
         .focus();
}


