//==============================================================================
// MCGAPIFlash.js
//
// OO and formatting changes by Stephen C. Fedder, March 2009
//==============================================================================

var notattempted_keyword="not attempted"; // not attempted keyword
var incomplete_keyword="incomplete";      // incomplete keyword
var completed_keyword="complete";         // completed keyword - should be "completed", but API code uses "complete"


//==============================================================================
//==============================================================================
// SCO Object Definition
//==============================================================================
//==============================================================================

//==============================================================================
// SCO object reference globals
//
var SCOGroup;         // SCO list
var g_parents;        // current SCO parents build hierarchy
var g_plevel;         // current SCO parent level

var CurrentID=-1;     // current SCO index in the course
var CurrentSCO=null;  // current SCO reference in the course
var TV=null;          // SCO menu TreeView object

//==============================================================================
// define a SCO
//
function DefineSCO(level,btype,iconSet,hasChild,url,title,vis) {
  if (typeof(vis)!="boolean") vis=true;
  if (!SCOGroup) {
    SCOGroup=new Array();
    g_parents=null;
  }
  SCOGroup.push(new SCO(level,btype,iconSet,hasChild,title,url,SCOGroup.length,vis));
}
//==============================================================================
// SCOs definition complete - re-prime parents variable for menu creation phase
//
function DefineSCO_Complete() {
  g_parents=null;
}
//==============================================================================
// SCO reference object constructor
//
function SCO(level,btype,iconSet,hasChild,title,url,index,vis) {
  // if not defined, define initial parent levels list
  if (!g_parents) {
    g_parents=[-1];
    g_plevel=0;
  }
  // unstack the parent level if this level is less than the parent
  while (level<g_plevel) {
    g_parents.pop(); g_plevel--;
  }
  // stack the parent level if this level is greater than the parent (indent)
  while (this.level>g_plevel) {
    g_parents[g_plevel+1]=g_parents[g_plevel]; g_plevel++;
  }
  this.level=level;
  this.btype=btype;
  this.iconSet=iconSet;
  this.index=index;
  this.title=title;
  this.url=url;
  this.hasURL=((typeof(this.url)=="number")||((typeof(this.url)=="string")&&(this.url!="")));
  if (this.hasURL&&isNumeric(this.url))
    this.url="shell.swf?scene="+this.url;
  this.hasChild=(typeof(hasChild)=="boolean")?hasChild:false;
  this.bookmark=0;
  this.parent=g_parents[g_plevel];
  this.visible=vis;
  // if this is a parent, stack as the next parent
  if (this.hasChild) {
    g_parents[++g_plevel]=index;
  }
}
//==============================================================================
// define SCO object properties
SCO.prototype.index;      // index in the SCOGroup
SCO.prototype.level;      // indent level (0==root)
SCO.prototype.title;      // title text
SCO.prototype.hasURL;     // true if has a non-blank url
SCO.prototype.url;        // url (no url == "")
SCO.prototype.hasChild;   // true if has children
SCO.prototype.btype;      // SCO bookmark type (0=immediate, 1=delayed)
SCO.prototype.iconSet;    // SCO icon set references object in iconSets (ic,io for folder closed/open icons, b0-b2 for bookmark icons)
SCO.prototype.bookmark;   // SCO bookmark value 0/1/2 (specific to linked actionable item)
SCO.prototype.pbookmark;  // SCO parent bookmark value 0/1/2 (cumulative if parent bookmark)
SCO.prototype.cell;       // SCO cell div reference
SCO.prototype.uniqueId;   // SCO unique div id
SCO.prototype.parent;     // parent SCO index
//==============================================================================
// SCO method - create SCO menu tree item
SCO.prototype.CreateTreeItem=function() {
  // if not defined, define initial parent levels list
  if (!g_parents) {
    g_parents=[TV.rootCell];
    g_plevel=0;
  }
  // unstack the parent level if this level is less than the parent
  while (this.level<g_plevel) {
    g_parents.pop(); g_plevel--;
  }
  // stack the parent level if this level is greater than the parent (indent)
  while (this.level>g_plevel) {
    g_parents[g_plevel+1]=g_parents[g_plevel]; g_plevel++;
  }
  // only create the cell if the SCO is supposed to be visible
  if (this.visible) {
    // create the cell in the current parent cell
    var cell=TV.CreateTreeItem(this,g_parents[g_plevel],this.level,this.hasChild);
    // if this is a parent, stack as the next parent
    if (this.hasChild) {
      g_parents[++g_plevel]=cell;
    }
    this.cell=cell;
  }
}
//==============================================================================
// SCO method - load SCO
SCO.prototype.Load=function() {
  if (this.hasURL) WriteHTMLFlash(this.url);
}

//==============================================================================
//==============================================================================
// Course SCO Processing - routines called from Flash
//==============================================================================
//==============================================================================

//==============================================================================
function SWFSetVariable(n,v) {
  try {
  	if (window.swfSCO) window.document["swfSCO"].SetVariable(n,v);
    else if (document.swfSCO) document.swfSCO.SetVariable(n,v);
  } catch (e) {
    alert("error setting flash variable '"+n+"' to '"+v+"'");
  }
}
function SCOGetValue(p_sLMSvar, p_sLMSval) {
  //-- ----------------------------------------------------
  //-- Copyrights: ©McGill Digital Solutions 2006
  //-- Created By:
  //-- Created On:
  //-- Purpose: this function is called by swf
  //-- Inputs:     NONE
  //-- Outputs:    NONE
  //-- Change Log:
  //--        [May29, 2006, A. L.] - update for CD SC
  //----------------------------------------------------
  //trace("SCOGetValue('"+p_sLMSvar+"','"+p_sLMSval+"')");
  // default to completed_keyword
  var retVal=completed_keyword;
  var bmVal=completed_keyword;
  if (CurrentID>=0) {
    switch (CurrentSCO.bookmark) {
      case 0: bmVal=notattempted_keyword; break;
      case 1: bmVal=incomplete_keyword; break;
      case 2: bmVal=completed_keyword; break;
    }
  }
  // note (steve): not sure why this is being set?
  // these are setting SCO variables to the value passed and completed state
  SWFSetVariable("commState",p_sLMSval);
  SWFSetVariable("lesson_status",bmVal);
  switch (p_sLMSvar) {
    case "lesson_status":
      retVal=bmVal;
      break;
  }
  // set the value being returned by the LMS
  SWFSetVariable("tempLMSValue",retVal);
}
//==============================================================================
function SCOSetValue(p_sLMSvar, p_sLMSval) {
  //-- ----------------------------------------------------
  //-- Copyrights: ©McGill Digital Solutions 2006
  //-- Created By:
  //-- Created On:
  //-- Purpose: this function is called by swf
  //-- Inputs:     NONE
  //-- Outputs:    NONE
  //-- Change Log:
  //--        [May29, 2006, A. L.] - update for CD SC
  //----------------------------------------------------
  //trace("SCOSetValue('"+p_sLMSvar+"','"+p_sLMSval+"')");
  switch (p_sLMSvar) {
    case "lesson_status":
      switch (p_sLMSval) {
        case notattempted_keyword:
          BookmarkSCO(CurrentID,0);
          break;
        case incomplete_keyword:
          BookmarkSCO(CurrentID,1);
          break;
        // allow both forms
        case "complete":
        case "completed":
          BookmarkSCO(CurrentID,2);
          //trace("SCOFinish="+SCOFinish);
          break;
      }
  }
}
//==============================================================================
function SCOFinish(p_var) {
  //-- ----------------------------------------------------
  //-- Copyrights: ©McGill Digital Solutions 2006
  //-- Created By:
  //-- Created On:
  //-- Purpose: this function is called by click DONE button on SCO
  //-- Inputs:     NONE
  //-- Outputs:    NONE
  //-- Change Log:
  //--        [May29, 2006, A. L.] - update for CD SC
  //----------------------------------------------------
  //trace("SCOFinish('"+p_var+"')");
  // if requested to complete the SCO on SCOFInish, bookmark the SCO complete
  if (SCOCompleteOnFinish) {
    BookmarkSCO(CurrentID,2);
  }
  // move on to the next sequential SCO
  MoveNext();
}
//==============================================================================
// SCOForward called when the SCO wants to go back to the previous SCO
// (not very intuitive)
//
function SCOForward() {
  //trace("SCOForward()");
  MovePrev();
}
// =============================================================================
// called by the sco to open a file url in a separate window
//
function SCOGetURL(p_strFileName) {
  //trace("SCOGetURL('"+p_strFileName+"')");
  if ((p_strFileName.indexOf("http:")>=0)||(p_strFileName.indexOf("https:")>=0))
    window.open(p_strFileName,"winPop")
  else
    window.open("sco/pdf/"+p_strFileName,"winPop")
}
//==============================================================================
function isNumeric(s) {
  if (typeof(s)=="number") return true;
  if (typeof(s)!="string") return false;
  if (s=="") return false;
  var c; for (var i=0; i<s.length; i++) {
    c=s.charAt(i); if (c<"0"||c>"9") return false;
  }
  return true;
}
//==============================================================================
//==============================================================================
// Course menu processing / navigation functions
//==============================================================================
//==============================================================================

//==============================================================================
// write the flash SCO load to the SCO div layer
//
function WriteHTMLFlash(p_valRef) {
  //-- ----------------------------------------------------
  //-- Copyrights: ©McGill Digital Solutions 2004
  //-- Created By:
  //-- Created On:
  //-- Purpose:
  //-- Inputs:     NONE
  //-- Outputs:    NONE
  //-- Change Log:
  //--    [Jun-09-2004, IAG] - Added comments in this function
  //--        [Dec-23-2004, A. L.] - Update File Path with Base setup from flash developer
  //--               - only this project right now
  //--        [May29, 2006, A. L.] - update for CD SCO
  //----------------------------------------------------
  if (p_valRef&&p_valRef.length>0) {
    var sFullFilePath=SCOBase+p_valRef;
    //trace("loading "+sFullFilePath);
    var objLMSSCO=document.getElementById("lms_sco");
    var html="<OBJECT id='swfSCO' WIDTH='"+SCOWidth+"' HEIGHT='"+SCOHeight+
      "' classid='clsid:D27CDB6E-AE6D-11cf-96B8-444553540000' "+
      "codebase='http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=5,0,0,0'>"+
      "<PARAM NAME='movie' VALUE='"+sFullFilePath+"'>"+
      "<PARAM NAME='quality' VALUE='high'>"+
      "<PARAM NAME='bgcolor' VALUE='"+SCOBgColor+"'>"+
      "<PARAM NAME='wmode' VALUE='"+SCOWMode+"'>"+
      "<PARAM NAME='allowscriptaccess' VALUE='always'>"+
      "<PARAM NAME='play' VALUE='true'>"+
      "<PARAM NAME='loop' VALUE='false'>"+
      "<PARAM NAME='base' VALUE='"+SCOBase+"'>"+
      "<EMBED src='"+sFullFilePath+"' width='"+SCOWidth+"' height='"+SCOHeight+
      "' swliveconnect='true' allowscriptaccess='always' quality='high' bgcolor='"+SCOBgColor+"' wmode='"+SCOWMode+
      "' name='swfSCO' play='true' loop='false' type='application/x-shockwave-flash' base='"+SCOBase+
      "' PLUGINSPAGE='http://www.macromedia.com/go/getflashplayer'></EMBED></OBJECT>";
    objLMSSCO.innerHTML=html;
    //trace("html:"+objLMSSCO.innerHTML);
  }
}
//==============================================================================
// create the SCO menu
//
function CreateSCOMenu() {
  // create menu tree view
  TV=new TreeView(NavWidth);
  // set the tree view sizing parameters
  TV.levelspacing=NavLevelSpacing;
  // initialize the tree nav in the lms_nav div
  TV.Initialize('lms_nav');
  // create SCO menu items
  for (var i=0; i<SCOGroup.length; i++)
    SCOGroup[i].CreateTreeItem();
  // clear all menu navigation highlights
  ClearMenuHighlights();
}
//==============================================================================
// initialize the class of menu items for all SCOs (unselect all)
//
function ClearMenuHighlights() {
  var each; for (var i=0; i<SCOGroup.length; i++) {
    each=document.getElementById("TDA"+SCOGroup[i].uniqueId);
    if (each) each.className='navnotselected';
  }
}
// =============================================================================
// highlight (only) the selected sco
//
function Highlight(sco_idx) {
  //trace("Highlight("+sco_idx+")");
  ClearMenuHighlights();
  if (sco_idx>=0) {
    // highlight current item
    var obj=document.getElementById("TDA"+SCOGroup[sco_idx].uniqueId);
    if (obj!=null) obj.className='navselected';
  }
}
//==============================================================================
// collapse all SCO menu levels unconditionally
//
function CollapseAllSCOs() {
  var uid,div,sco;
  for (var i=0; i<SCOGroup.length; i++) {
    var sco=SCOGroup[i]; if (sco.hasChild) {
      uid=SCOGroup[i].uniqueId;
      div=document.getElementById("D"+uid); if (div) {
        if (div.style.display!="none") {
          div.style.display="none";
        }
      }
    }
  }
}
//==============================================================================
// collapse all SCO menus except the one the selected sco is in
//
function CollapseAll(sco_idx) {
  // collapse all the SCO submenus
  CollapseAllSCOs();
  if (sco_idx>=0) {
    // if this sco is not in the root level, open the sco parent menu hierarchy
    var sco=SCOGroup[sco_idx]; if (sco.level>0) {
      var uid,cdiv; while (sco.parent>=0) {
        sco=SCOGroup[sco.parent];
        uid=sco.uniqueId;
        cdiv=document.getElementById("D"+uid);
        if (cdiv&&cdiv.style.display=="none") {
          cdiv.style.display="block";
        }
      }
    }
  }
}
//==============================================================================
// goto loop sco
//
function LoadLoopSCO() {
  if (LoopSCO!="") {
    //trace("LoadLoopSCO");
    // collapse all scos menus
    CollapseAllSCOs();
    // set current sco id to loop (-1)
    CurrentID=-1;
    // clear all menu navigation highlights
    ClearMenuHighlights();
    // start the intro loop
    WriteHTMLFlash(LoopSCO);
  } else {
    LoadSCO(0);
  }
}
//==============================================================================
// get the cumulative bookmark for a folder sco and set the actual
//
function CalculateSCOBookmark(sco) {
  var sco_idx=sco.index;
  // if the folder has no actual bookmark state, start with a completion state
  var bmstate=sco.hasURL?sco.bookmark:2;
  if (sco.hasChild) {
    var csco; for (i=0; i<SCOGroup.length; i++) {
      csco=SCOGroup[i]; if (csco.parent==sco_idx) {
        if (csco.hasChild) {
          switch (csco.pbookmark) {
            case 0: if (bmstate==2) bmstate=1;
            case 1: bmstate=1; break;
            case 2: if (bmstate==0) bmstate=1;
          }
        } else {
          switch (csco.bookmark) {
            case 0: if (bmstate==2) bmstate=1;
            case 1: bmstate=1; break;
            case 2: if (bmstate==0) bmstate=1;
          }
        }
      }
    }
    // if folder bookmark is changing, set the folder bookmark and update the graphic
    if (bmstate!=sco.pbookmark) {
      sco.pbookmark=bmstate;
      if (sco.iconSet) {
        var ics=iconSets[sco.iconSet]; if (ics) {
          var bmpath=ics["b"+bmstate]; if (bmpath) {
            // add bookmark to the highlighted item
            var div=document.getElementById("B"+sco.uniqueId); if (div) {
              div.setAttribute("src",bmpath);
            }
          }
        }
      }
    }
  }
  //trace("CalculateSCOBookmark sco_idx="+sco_idx+" bmstate="+bmstate);
  // return the found folder bookmark state
  return bmstate;
}
//==============================================================================
// bookmark the specified actionable sco to the specified bookmark state
// and update the cascading menu marks to reflect the new state
//
function BookmarkSCO(sco_idx,bmstate) {
  //trace("BookmarkSCO("+sco_idx+","+bmstate+")");
  // ignore the loop sco, if present
  if (sco_idx<0) return;
  var sco=SCOGroup[sco_idx],i;
  // entering the sco?
  if ((bmstate<0)||(bmstate>2)) {
    // if the bookmark has already been set, leave it alone
    if (sco.bookmark>0) return;
    bmstate=(sco.btype==0)?2:1;
  }
  // if the bookmark is not changing, leave it alone
  if (sco.bookmark!=bmstate) {
    // set the actual sco bookmark state
    sco.bookmark=bmstate;
    // if the item is a menu, determine the folder bookmark state based on the children and the final bookmark state
    if (sco.hasChild)
      CalculateSCOBookmark(sco);
    else {
      // otherwise set the physical bookmark for the item
      if (sco.iconSet) {
        var ics=iconSets[sco.iconSet]; if (ics) {
          var bmpath=ics["b"+bmstate]; if (bmpath) {
            // add bookmark to the highlighted item
            var div=document.getElementById("B"+sco.uniqueId); if (div) {
              div.setAttribute("src",bmpath);
            }
          }
        }
      }
    }
    // ok, now update the parent scos to indicate the new state
    while (sco.parent>-1) {
      sco=SCOGroup[sco.parent]; CalculateSCOBookmark(sco);
    }
  }
}
//==============================================================================
// load next actionable item at sco index specified
//
function LoadSCO(sco_idx) {
  if (sco_idx<0) {
    //trace("LoadSCO - LoadLoopSCO");
    LoadLoopSCO();
  } else {
    // find the next sequential actionable sco
    var sco; while (sco_idx<SCOGroup.length) {
      sco=SCOGroup[sco_idx];
      if (sco.hasURL) break;
      sco_idx++;
    }
    // forward at the end goes back to the loop sco
    if (sco_idx>=SCOGroup.length) {
      //trace("LoadSCO - LoadLoopSCO");
      if (LoopSCO!="") LoadLoopSCO();
    } else {
      //trace("LoadSCO - sco_idx="+sco_idx);
      // make the sco visible in the menu
      CollapseAll(sco_idx);
      // load the sco
      CurrentID=sco_idx;
      CurrentSCO=sco;
      Highlight(CurrentID);
      BookmarkSCO(CurrentID,-1);
      CurrentSCO.Load();
    }
  }
}
//==============================================================================
// move to next sequential actionable SCO
//
function MoveNext() {
  // try loading the next sco
  if (++CurrentID<SCOGroup.length) {
    //trace("MoveNext() - CurrentID="+CurrentID);
    LoadSCO(CurrentID);
  // next at the end of scos goes back to the loop
  } else {
    //trace("MoveNext() - LoadLoopSCO");
    LoadLoopSCO();
  }
}
//==============================================================================
// move to the previous sequential actionable SCO
//
function MovePrev() {
  // locate the first prior actionable SCO in the course relative to the current sco
  if (CurrentID>=0) {
    CurrentID--; while ((CurrentID>=0)&&(!SCOGroup[CurrentID].hasURL)) {
      CurrentID--;
    }
  }
  //trace("MovePrev() - CurrentID="+CurrentID);
  // load the selected sco
  LoadSCO(CurrentID);
}
//==============================================================================
// process menu click action
//
function Click(tv_idx,sco_idx) {
  var sco=SCOGroup[sco_idx];
  // parent node with children only (no link)
  if ((!sco.hasURL)&&(!SCOFolderLinkNearest)) {
    //trace("Click - Toggle="+sco.uniqueId);
    TV.Toggle(sco.uniqueId);
  // node with link - load the sco
  } else {
    //trace("Click - LoadSCO="+sco_idx);
    LoadSCO(sco_idx);
  }
}
function ClickFolder(tv_idx,sco_idx) {
  var sco=SCOGroup[sco_idx];
  // parent node with children only (no link)
  if (!sco.hasURL) {
    //trace("Click - Toggle="+sco.uniqueId);
    TV.Toggle(sco.uniqueId);
  // node with link - load the sco
  } else {
    //trace("Click - LoadSCO="+sco_idx);
    LoadSCO(sco_idx);
  }
}
// =============================================================================
function popupWindow(url,width,height) {
  var openWin=window.open("sco/500/"+url,"","width="+width+",height="+height+",toolbar=no,scrollbars=no,location=no,directories=no,menubar=no,resizable=no,status=no");
}
// =============================================================================


