//=============================================================================
//
//@doc EXTERNAL
//
//@module utils.js   |  Utilities for Javascript
//
// ----------------------------------------------------------------------------
// COPYRIGHT 1999 DELCAM PLC., BIRMINGHAM, ENGLAND. 
// ----------------------------------------------------------------------------
//
// History.
// Who When     What   
// --- -------- ---------------------------------------------------------------
// tpb 08/12/99 Written
// ejp 15/01/03 Added GetSelectedRadioIndex
// pah 14/12/04 Added StoreDoubleDimension, RetrieveDoubleDimension,
//              SetToolpathDimension, GetToolpathDimension which all adjust
//              for model units automatically
// pah 14/06/05 DepthToAbsZ() calls into ArtCAM
// ejp 12/06/07 Moved TPBs GetFrameCommandLine here from 2-rail sweep - returns ? arguments for a page
//-----------------------------------------------------------------------------


// Color shade and converting functions ---------------------------------------
function GetColorShade(color1, weight1, color2, weight2)
{
    // tpb: Work out a nice half colour shade between the colors to the ratio given. A bit of bit shifting fun this...
    var totalweight = weight1 + weight2;
    return ((Math.round( (  (color1&0xff)         *weight1 +  (color2&0xff)         *weight2)/totalweight ))<<16) + 
           ((Math.round( ( ((color1&0xff00)  >>8) *weight1 + ((color2&0xff00)  >>8) *weight2)/totalweight ))<<8 ) + 
             Math.round( ( ((color1&0xff0000)>>16)*weight1 + ((color2&0xff0000)>>16)*weight2)/totalweight );    
}

function ColorToString( color )
{
   // Return the color with radiix set to base 16
   return "#" + color.toString(16);
}


// Rounding and units functions -----------------------------------------------
function Round( number, dp )
{
   if( dp > 6 )
   {
      artcam.MessageBox("Cannot round to decimal places greater than 6");
      return;
   }
   var shift = Math.pow(10,dp);
   return Math.round( number * shift ) / shift;
}

function RoundUnits( number )
{
   var dp = artcam.Relief.InMM ? 3 : 4;
   return Round( number, dp );
}

function Units()
{
   return artcam.InMM ? "mm" : "inches";
}

// === DepthToAbsZ ========================================
//
// Turns a Depth value given from the top of the material down,
// entered by the user, into a real Z value taking into account
// Z Zero.
//
function DepthToAbsZ(depth)
{
   return artcam.DepthToAbsZ(depth);
}

// === AbsZToDepth ========================================
//
// Turns an AbsZ value given from the base of the material up,
// entered by the user, into a depth value taking into account
// Z Zero. 
//
function AbsZToDepth(absz)
{
   return artcam.AbsZToDepth(absz);
}


// === SetUnitsSpans ========================================
//
// Replace all tags displaying units with correct units
//

function SetUnitsSpans()
{
   // Replaces '<span units></span>' with inches or mm.
   var tags = document.all.tags("SPAN");
   var idx, tag;
   var count = tags.length;
   for( idx = 0; idx < count; idx ++ )     
      {
      tag = tags[idx];
      if ( tag.units != null )               
         tag.innerText = Units();
      }
}


// Expandable Lists -----------------------------------------------------------
//
function ExpandItem( collapseItem, collapseList )
{
   if( collapseItem.style.display != "none" )
   {
      // If the collapseItem is open, then we simply close it.
      collapseItem.style.display = "none";
   }
   else
   {
      // Otherwise we collapse all the div's in the list
      for(var i = 0; i < collapseList.length; ++i )
         collapseList[i].style.display = "none";

      // Now display the selected div.
      collapseItem.style.display = "";
   }
}

function ExpandAll( collapseList )
{
   // Expand all the items in the collapse list.
   for(var i = 0; i < collapseList.length; ++i )
      collapseList[i].style.display = "";
}

function CollapseAll( collapseList )
{
   // Collapse all the items in the collapse list.
   for(var i = 0; i < collapseList.length; ++i )
      collapseList[i].style.display = "none";
}




// Toggling visibility --------------------------------------------------------
//
//
function ToggleVisibility( toggleItem )
{
   // Toggles the visibility of an item
   if( toggleItem.style.display != "none" )
      toggleItem.style.display = "none";
   else
      toggleItem.style.display = "";
}


// toggling keeping preview vectors -------------------------------------
function ToggleKeepPreviewVectors ( )
{
artcam.Machining.KeepPreviewVectors = event.srcElement.checked;
}

// MakeButtonsSameSize --------------------------------------------------------
//
//
function MakeButtonsSameSize()
{
  var max_width = 0;
  
  for ( var i = 0 ; i < arguments.length ; i++ )
  {
    if ( arguments[i].clientWidth > max_width )
      max_width = arguments[i].clientWidth;
  }
  
  for ( var i1 = 0 ; i1 < arguments.length ; i1++ )
  {
     arguments[i1].width = max_width + 4;
  }
}

// Override alert to Allow it to cancel ---------------------------------------
//
// 
var continue_alert = 1;
function alert(msg)
{
   if( continue_alert )
      continue_alert = window.confirm(msg + "\n\n(Press Cancel to stop alert's until page is refreshed)");
}



// GetCommandLine ---------------------------------------
//
// Returns the search string, stripped of unwanted characters 
//
function GetCommandLine()
{
  // We get the href passed in at the top level
  var searchString = parent.location.href;

  // And perform a regexp to remove an unwanted beginning
  // REGEXP BREAKDOWN
  //   /<regexp>/i = Match Case Insensitive
  //   ^         Match must include begining of string
  //   .*        Followed by zero or more occurances of any character up to...
  //   (<group>) a single occurance of something in this group, which is...
  //   \?        Either a question mark
  //   |         OR
  //   \%3F      %3F
  if( searchString.search( /^.*(\?|\%3F)/i ) != -1 )
    return searchString.replace( /^.*(\?|\%3F)/i, "");
  else
    return ""; // Return an empty string if no match
} 
  
// === ToggleHelp =======================================
//
// Toggle display of help divs
//
// ejp 14/06/04 - Default toggle help functionality that simply changes visibility of tagged objects
//
function ToggleHelp()
{
   ToggleHelpSpanVisibility();
}

// === ToggleHelpSpanVisibility ===============================================
//
// Toggle visibility of help spans (with tag HELPTAG)
//
// History
// Who When     What
// --- -------- ---------------------------------------------------------------
// tpb 21/08/01 Optional argument to specify a different kind of tag
// pah 02/11/07 Added optional featureHelp tag, for licenced help
//-----------------------------------------------------------------------------
function ToggleHelpSpanVisibility()
{
   // The tag type may have been passed in.
   // If not we default to "TR"
   var tagType = "TR";
   if( arguments.length != 0 )
      tagType = arguments[0];

   var tags = document.all.tags(tagType);
   var idx, tag;
   var count = tags.length;

   for( idx = 0; idx < count; idx ++ ) {    
   
      tag = tags[idx];
      if ( tag.HELPTAG != null ) {
         // Check for a licenced feature tag
         if (tag.featureHelp != null) {
            if (!artcam.IsFeatureLicensed(eval(tag.featureHelp))) 
               // Not licenced so skip this help
               continue; 
         }  
         // Toggle regardless                 
         ToggleVisibility(tag);
      }
   }
}


//=== SetHelpSpanVisibility ==============================================
//
// Sets the Help Span visibility directly according to artcam.DisplayHelp status
//
// History
// Who When     What
// --- -------- ---------------------------------------------------------
// ejp 31/08/04 Written
//-----------------------------------------------------------------------

function SetHelpSpanVisibility()
{
   var tagType = "TR";
   if( arguments.length != 0 )
      tagType = arguments[0];
   
   var tags = document.all.tags(tagType);
   var idx, tag;
   var count = tags.length;
   for( idx = 0; idx < count; idx ++ )     
   {
      tag = tags[idx];
      if ( tag.HELPTAG != null )
      {
         tag.style.display = artcam.DisplayHelp ? "" : "none";
      }
   }
}

// === ImportScript =============================================
//
// Import passed script into current file
//

function ImportScript(scriptname)
{
  document.write("<script src='" + scriptname + "'><\/script>");
}




//=== LimitSpan ==============================================
//
// Limits the width of a span to given size, and applies hovertext if passed in
//
// History
// Who When     What
// --- -------- ---------------------------------------------------------
// tpb 14/03/03 Written
//-----------------------------------------------------------------------

function LimitSpan(span, text, size, hovertext)
{
   // Set the span to the full text
   span.innerText = text;
   if( typeof(hovertext) != "undefined" )
      span.title = ( span.offsetWidth > size ? hovertext : "" );

   // If the span is too big, we change the text to trailing dots until we can get rid of no more
   var idx = text.length - 2;
   while( span.offsetWidth > size && idx > 2)
   {
      span.innerText = text.substring(0,idx) + "...";
      idx -= 1;
   }
}



//=== ShowVideo ==============================================
//
// History
// Who When     What
// --- -------- ---------------------------------------------------------
// sap 29/08/01 Written
// tpb 12/04/05 Use script Web Page opener to get around new security issues
//-----------------------------------------------------------------------

function ShowVideo( file_name )
{
   var full_file_name = top.external.GetAVIPath( file_name );

   if ( full_file_name != "" )
   {
      OpenBrowser( full_file_name );
   }
   else
   {
     artcam.MessageBox( gCDinCDDrive );
   }
}


//=== OpenBrowser ==============================================
//
// Opens the Default browser with the page passed in.
//
// History
// Who When     What
// --- -------- ---------------------------------------------------------
// tpb 20/04/05 Written
//-----------------------------------------------------------------------


function OpenBrowser(theurl)
{
   // Internal ArtCAM Opener
   top.external.OpenHtmlWindow(theurl);

   // Script Opener, currently used in previous versions of ArtCAM
   /*
   try 
   {
      // Read Registry Key
      var WshShell = top.external.CreateActiveXObject("WScript.Shell");
      var browser = WshShell.RegRead( "HKCR\\htmlfile\\shell\\open\\command\\" );
      
      // Cut out the first quoted part - this is the browser exe
      if( /^.*?(\".*?\")/.test( browser ) )
      {
         // We found the browser
         browser = RegExp.$1;
         
         // Now add the URL and execute this in the shell
         WshShell.Exec( browser + ' "' + theurl + '"');
      }
      else
         throw(new Object());
   }
   catch(e)
   {   
      artcam.MessageBox(gCouldNotOpenBrowser);
   }
   */

}


//=== GetSelectedRadioIndex ==============================================
//
// Helper function to return the index of the checked radio button in a collection
//
// History
// Who When     What
// --- -------- ---------------------------------------------------------
// ejp 08/01/03 Written
//-----------------------------------------------------------------------

function GetSelectedRadioIndex(radio_collection)
{
   for(var index = 0; index<radio_collection.length; index++)
   {
      if(radio_collection[index].checked==true)
         return index;
   }
}


//=== GetCurrentDir ==============================================
//
// Returns directory of current html file - returned directory
// includes the trailing slash
//

//
// History
// Who When       What
// --- ---------- ---------------------------------------------------------
// bem 14/03/2003 Written
// ----------------------------------------------------------------------

function GetCurrentDir()
{
   // Where is this HTML file sitting - all our files are stored in a directory below called Code
   var HTMLDir = unescape(document.location);                         // Get a cleanish location string
   HTMLDir = HTMLDir.replace(/^file\:\/\/\/(.*)\/.*?$/, "$1\\"); // This reg exp strips away 'file:///' and the file at the end and leaves a \ at the end
   HTMLDir = HTMLDir.replace(/\//g, "\\");                       // Then we replace all backslashes with forward slashes 

   return HTMLDir;
}


//=== MoveSelectionToLayer ==============================================
//
// Moves the currently selected vectors to the layer with the passed name
// if the layer does not exist then it is created. RGB colours are optional
//
// History
// Who When     What
// --- -------- ---------------------------------------------------------
// ejp 16/12/03 Written
//-----------------------------------------------------------------------

function MoveSelectionToLayer
   (
    layer_name,        // String for layer name
    layer_colour_red,  // Optional colour arguments for specified layer
    layer_colour_green,
    layer_colour_blue
    ) 
{
   if (layer_name == "")
      return true;   // nothing to do
   
   // find layer ....
   var layer_idx = artcam.VectorLayers.FindName(layer_name,false);
   
   if (layer_idx == -1)
   {
      // layer doesnt exist - create it
      layer_idx = artcam.VectorLayers.Create(-1,layer_name);
      if (layer_idx == -1)
         return false; // failed to create layer
      
      var layer_obj = artcam.VectorLayers.GetLayer(layer_idx);
      if (layer_obj != null)
      {
         if(typeof(layer_colour_red) != "undefined")
            layer_obj.colorR = layer_colour_red;
         
         if(typeof(layer_colour_green) != "undefined")
            layer_obj.colorG = layer_colour_green;
         
         if(typeof(layer_colour_blue) != "undefined")
            layer_obj.colorB = layer_colour_blue;
      }
      // set default colour for vectors on this layer
   }
   // Set the selected vectors layers
   artcam.VectorSelection.SetAllLayers(layer_idx);
}


//=== StoreDoubleDimension ====================================================
//
// Stores a double and handles units automatically.
//
// The name is appended with "MM" and value always stored as mm, then 
// saved via artcam. The conversion factor is 25 to keep decimals clean.
//
// value is assumed to be in model units
//
// History
// Who When     What
// --- -------- ---------------------------------------------------------------
// pah 14/12/04 Written
//-----------------------------------------------------------------------------
function StoreDoubleDimension( key, name, value )
{
   if (Units() == "inches") 

      artcam.StoreDouble( key, name + "MM", value*25 );

   else

      artcam.StoreDouble( key, name + "MM", value );    
}


//=== RetrieveDoubleDimension =================================================
//
// Retrieve a double in current model units. However the default value you
// supply must be in mm. <= read this!!!
//
// The name is appended with "MM" and searched for by artcam.
// Since the value is always in mm (see StoreDouble) the value is scaled
// as required. The conversion factor is 25 to keep decimals clean.
//
// History
// Who When     What
// --- -------- ---------------------------------------------------------------
// pah 14/12/04 Written
//-----------------------------------------------------------------------------
function RetrieveDoubleDimension( key, name, value )
{
   var v = artcam.RetrieveDouble( key, name + "MM", value );

   if (Units() == "inches") 
      v /= 25;

   return v;
}



function SetToolpathDimension( toolpath, name, value )
{
   toolpath.SetDimension( name, value );
}


function GetToolpathDimension( toolpath, name, value )
{
   return toolpath.GetDimension( name, value );
}

//=== GetFrameCommandLine =================================================
//
// Return 'command line' for page (string following a '?')
//
// History
// Who When     What
// --- -------- ---------------------------------------------------------------
// ejp 12/06/07 Moved here from 2-rail sweep for re-use
//-----------------------------------------------------------------------------
function GetFrameCommandLine()
{
  // We get the href passed in at the top level
  var searchString = top.location.href;

  // And perform a regexp to remove an unwanted beginning
  // REGEXP BREAKDOWN
  //   /<regexp>/i = Match Case Insensitive
  //   ^         Match must include begining of string
  //   .*        Followed by zero or more occurances of any character up to...
  //   (<group>) a single occurance of something in this group, which is...
  //   \?        Either a question mark
  //   |         OR
  //   \%3F      %3F
  if ( searchString.search( /^.*(\?|\%3F)/i ) != -1 )
     {
     searchString = searchString.replace( /^.*(\?|\%3F)/i, "");
     searchString = unescape(searchString);
     searchString = searchString.replace( /\//g, "\\");
     return searchString;
     }
  else
     {
     return ""; // Return an empty string if no match
     }
}   