////////////////////////////////VTOURPLAYER FRAMEWORK : BEG////////////////////////////////

///GENERAL FRAMEWORK : BEG///

var g_rgPlayerTags                      = new Array();  //ID's of player DHTML object tags
var g_oVTours                           = new mDict();  //Tour dictionary object.
var g_oVTourPlayers                     = new mDict();  //Tour Player dictionary object.
var g_oTourImages                       = new mDict();  //Tour Player dictionary object.
var g_oVTInterval;                                      //Interval object to control all scrolling.
var g_iIntervalTimer                    = 20;           //Default interval delay in milliseconds.
var g_bTenaciousShow                    = false;        //Tenacity flag for use by ShowVTours
var g_sTourImageBaseURL                 = "http://media.expedia.com";

//Constants : General
var c_iPlayerTypeFloat                  = 1;
var c_iPlayerTypeInline                 = 2;
var c_iMinVTourWidth                    = 363;
var c_iVTourHeight                      = 238;
var c_iPlayB                            = 0
var c_iPlayP                            = 1;
var c_iPlayF                            = 2;
var c_FloatingPlayerAnchorOffsetY       = -125;
var c_FloatingPlayerAnchorOffsetXLeft   = -40;
var c_FloatingPlayerAnchorOffsetXRight  = -237;
var c_FloatingPlayerImageOffsetY        = 0;
var c_FloatingPlayerImageOffsetXLeft    = 0;
var c_FloatingPlayerImageOffsetXRight   = -197;
var c_FloatingPlayerHeight              = 384;

var c_iRetryAttemptNum                  = 6;


//Constants : Used as "keys" to objects in VTourPlayer.Tags array.
//NOTES:1. Access to Tags objects should be made exclusively using these constants.
//      2. JScript does not support constants, DO NOT reassign to constants coding practice.
var iCtr                            = 0;
var cTagPlayer                      = iCtr++;
var cTagTourImg                     = iCtr++;
var cTagBtnOutForward               = iCtr++;
var cTagBtnOutBackward              = iCtr++;
var cTagBtnOutPause                 = iCtr++;
var cTagBtnInForward                = iCtr++;
var cTagBtnInBackward               = iCtr++;
var cTagBtnInPause                  = iCtr++;
var cTagCaption                     = iCtr++;

var cTagNavNextPrev                 = iCtr++;
var cTagNavLinkNext                 = iCtr++;
var cTagNavLinkPrev                 = iCtr++;
var cTagNavCtrTotal                 = iCtr++;
var cTagNavCtrCurrent               = iCtr++;

var cTourMsg                        = iCtr++;
var cImgBtnBackward                 = iCtr++;
var cImgBtnPause                    = iCtr++;
var cImgBtnForward                  = iCtr++;

var sBackwardSuffix                 = "_b";
var sPauseSuffix                    = "_p";
var sForwardSuffix                  = "_f";
var sButtonSuffix                   = "_btn";
var sImageSuffix                    = "_img";
var sPlayerSuffix                   = "";
var sPlayerTourImgSuffix            = "_tourimg";
var sTourMsgSuffix                  = "_tourmsg";
var sPlayerCaptionSuffix            = "_caption";
var sPlayerNavNextPrevSuffix        = "_navnextprev"
var sPlayerNavLinkNextSuffix        = "_navlinknext"
var sPlayerNavLinkPrevSuffix        = "_navlinkprev"
var sPlayerNavCountTotal            = "_tourctrtotal";
var sPlayerNavCountCurrent          = "_tourctrcurrent";
var sOutSuffix                      = "_out";
var sInSuffix                       = "_in";

//UI elements
g_rgPlayerTags[cTagPlayer]          = sPlayerSuffix;
g_rgPlayerTags[cTagTourImg]         = sPlayerTourImgSuffix;
g_rgPlayerTags[cTagCaption]         = sPlayerCaptionSuffix;

//UI next/prev nav elements
g_rgPlayerTags[cTagNavNextPrev]     = sPlayerNavNextPrevSuffix;
g_rgPlayerTags[cTagNavLinkNext]     = sPlayerNavLinkNextSuffix;
g_rgPlayerTags[cTagNavLinkPrev]     = sPlayerNavLinkPrevSuffix;
g_rgPlayerTags[cTagNavCtrTotal]     = sPlayerNavCountTotal;
g_rgPlayerTags[cTagNavCtrCurrent]   = sPlayerNavCountCurrent;

//UI nav buttons elements
g_rgPlayerTags[cTourMsg]            = sPlayerSuffix + sTourMsgSuffix;
g_rgPlayerTags[cTagBtnOutBackward]  = sButtonSuffix + sOutSuffix + sBackwardSuffix;
g_rgPlayerTags[cTagBtnOutPause]     = sButtonSuffix + sOutSuffix + sPauseSuffix;
g_rgPlayerTags[cTagBtnOutForward]   = sButtonSuffix + sOutSuffix + sForwardSuffix;
g_rgPlayerTags[cTagBtnInBackward]   = sButtonSuffix + sInSuffix  + sBackwardSuffix;
g_rgPlayerTags[cTagBtnInPause]      = sButtonSuffix + sInSuffix  + sPauseSuffix;
g_rgPlayerTags[cTagBtnInForward]    = sButtonSuffix + sInSuffix  + sForwardSuffix;
g_rgPlayerTags[cImgBtnBackward]     = sImageSuffix  + sBackwardSuffix;
g_rgPlayerTags[cImgBtnPause]        = sImageSuffix  + sPauseSuffix;
g_rgPlayerTags[cImgBtnForward]      = sImageSuffix  + sForwardSuffix;


////GENERAL HELPER FUNCTIONS : BEG////

function ClearVTInterval()
{
    if(g_oVTInterval != null)           clearInterval(g_oVTInterval);
}

//SIMULATES clicking on a remote anchor tag.
function ClickRemoteLink(sID)
{
    try
    {
        var sLnk = GE(sID).href;
        if(sLnk != null && sLnk.toLowerCase().indexOf("javascript") >= 0)
        {
            eval(unescape(sLnk.replace(/javascript:/gi,'')));
        }
        else
        {
            document.location.href=sLnk;
        }
    }
    catch(e)
    {
        Tst("ClickRemoteLink('" + sID + "') failed.");
    }
}

//CONVERT MediaDisplayMethodSeqNbr to boolean indicating whether tour is 360 or not
function ConvertDisplayIDToBool(iID)
{
    //2 and null treated as "180"
    var bReturn = true;
    if(iID == null || iID == 2) bReturn = false;

    return bReturn;
}

//CONVERT other media type references to v-tours (e.g. _b.jpg,_t.jpg, etc.)
function ConvertVtourImageRef(sImageRef){return sImageRef.replace(/_.\.jpg/g,"_v.jpg");}

//RETURNS start position as a number of pixels from left image border or null if image hasn't been loaded yet.
function GetStartPosPx(oTour)
{
    var iReturn = 0;
    if(oTour.Width != null) iReturn = - parseInt(oTour.StartPosPcnt * oTour.Width);

    return iReturn;
}

function GetTourImage(sID,sImgSrc)
{
    //LOAD image if not already loaded this page view.
    oImg    = g_oTourImages.get(sID);

    if(oImg == null)
    {
        oImg            = new Image();
        oImg.src        = sImgSrc;
        g_oTourImages.add(sID,oImg);
    }

    return g_oTourImages.get(sID);
}

//RETURNS timeout delay for current retry attemp (in milliseconds)
function GetTourLoadRetryDelay(iAttemptNum)
{
    var iReturn;
    if(iAttemptNum <= 1)        iReturn = 100;
    else if(iAttemptNum == 2)   iReturn = 500;
    else if(iAttemptNum == 3)   iReturn = 1000;
    else if(iAttemptNum == 4)   iReturn = 2000;
    else if(iAttemptNum == 5)   iReturn = 5000;
    else                        iReturn = 10000;

    return iReturn;
}

//GET tour from dictionary (if not exist CREATE then ADD)
function GetVTour(sName,sImgRef,sDisplayText,iStartPosPcnt,fIs360)
{
    var oVTour;
    if(g_oVTours.get(sName) != null)
    {
        oVTour = g_oVTours.get(sName);
    }
    else
    {
        oVTour   = new VTour(sName,sImgRef,sDisplayText,iStartPosPcnt,fIs360);
        if(oVTour != null && oVTour.IsInit) g_oVTours.add(sName,oVTour);
    }
    return oVTour;
}

//Get tour from dictionary (if not exist return null)
function GetVTourByID(sID)
{
    return g_oVTours.get(sID);
}

//GETS named player from dictionary, CREATES if not found
function GetVTourPlayer(sName)
{
    var oVTourPlayer;

    if(g_oVTourPlayers.get(sName) != null)
    {
        oVTourPlayer = g_oVTourPlayers.get(sName);
    }
    else
    {
        oVTourPlayer   = new VTourPlayer(sName);

        //ADD if valid
        if(oVTourPlayer.IsValid) g_oVTourPlayers.add(sName,oVTourPlayer);
        else Tst("Player object '" + sName + "' is invalid, unable to add to collection");
    }

    return oVTourPlayer;
}

function HidePlayer(sID)
{
    GetVTourPlayer(sID).Hide();
}

//PLAY BY ID + DIR : 1. Requires ID of target player and
//                   2. This function called by buttons in tour control UI
function PBID(sPlayerID,iConstPlayDir)
{
    var oPlayer                     = GetVTourPlayer(sPlayerID);
    if(iConstPlayDir != c_iPlayB && iConstPlayDir != c_iPlayP && iConstPlayDir != c_iPlayF)
    {
        Tst("Bad play direction constant:\t" + iConstPlayDir +"\nAcceptable values :\t\t" + c_iPlayB + ", " + c_iPlayP + ", or " + c_iPlayF);
        return;
    }

    //IF player state not ready for requested command, do nothing and return.
    if(oPlayer == null || oPlayer.CurrentTour == null || !oPlayer.ButtonState[iConstPlayDir]) return;
    oPlayer.CurrentTour.Direction   = iConstPlayDir - 1;
    oPlayer.SetNavUI();
    oPlayer.PlayCurrent();
}

//SCROLLS non-panoramic tour
function ScrollTour180(sID)
{
    var oVTP        = GetVTourPlayer(sID);
    var oTourImg    = oVTP.Tags[cTagTourImg];
    var oTour       = oVTP.CurrentTour;

    if(oTour.Direction == 2 || oTour.Direction == -2) return;

    var iWidth      = oTour.Width;
    var oLeft       = oVTP.ImgLeft;
    oLeft           -= (oTour.Direction * oTour.Speed);

    if (oLeft > 0)
    {
        oLeft -= iWidth;
    }
    else if(oLeft < (-iWidth))
    {
        oLeft += iWidth;
    }

    if(oLeft == 0)                              //HIT left side -> STOP
    {
        oTour.Direction = 2;
        oVTP.SetNavUI();
        SetVTInterval("",500);
    }
    else if(oLeft <= - (oTour.Width - 363))     //HIT right side -> STOP
    {
        oTour.Direction = -2;
        oVTP.SetNavUI();
        SetVTInterval("",500);
    }
    else
    {
        oVTP.ImgLeft        = oLeft;
        oTourImg.style.left = oLeft;
    }

}


function ScrollTour360(sID)
{
    var oVTP        = GetVTourPlayer(sID);
    var oTourImg    = oVTP.Tags[cTagTourImg];
    var oTour       = oVTP.CurrentTour;

    if(oTour == null) return;

    var iWidth      = oTour.Width;
    var oLeft       = oVTP.ImgLeft;
    oLeft           -= (oTour.Direction * oTour.Speed);

    if (oLeft > 0){oLeft -= iWidth;}
    else if(oLeft < (-iWidth)){oLeft += iWidth;}

    oVTP.ImgLeft        = oLeft;
    oTourImg.style.left = oLeft;
}

function SetButtonUI(oPlayer)
{
    var rgUI            = [1,1,1];
    var sWT             ="_white.gif";
    var sRG             ="_" + g_sRegionAbbr + ".gif";
    var sAB             ="VTALLBTN";
    var sRB             ="VTREGBTN";
    var sIP             = "/images/vtbtn_";

    var oBO             = oPlayer.Tags[cTagBtnOutBackward  ];
    var oPO             = oPlayer.Tags[cTagBtnOutPause     ];
    var oFO             = oPlayer.Tags[cTagBtnOutForward   ];
    var oBI             = oPlayer.Tags[cTagBtnInBackward   ];
    var oPI             = oPlayer.Tags[cTagBtnInPause      ];
    var oFI             = oPlayer.Tags[cTagBtnInForward    ];
    var oBBI            = oPlayer.Tags[cImgBtnBackward     ];
    var oPBI            = oPlayer.Tags[cImgBtnPause        ];
    var oFBI            = oPlayer.Tags[cImgBtnForward      ];

    var iDir            = 0;
    if(oPlayer.CurrentTour != null) iDir = oPlayer.CurrentTour.Direction;

    switch(iDir)
    {
        case -2 : //180 : paused at left edge
            rgUI[1] = 0;
            rgUI[2] = 0;
        break;
        case -1 : //all : backward
            rgUI[0] = 0;
        break
        case 0  : //all : paused
            rgUI[1] = 0;
        break;
        case 1  : //all : forward
            rgUI[2] = 0;
        break;
        case 2 : //180  : paused at right edge
            rgUI[0] = 0;
            rgUI[1] = 0;
        break;
    }

    oBO.className = sAB + (rgUI[0] ^ 1);
    oPO.className = sAB + (rgUI[1] ^ 1);
    oFO.className = sAB + (rgUI[2] ^ 1);

    oBI.className = sRB + (rgUI[0] ^ 1);
    oPI.className = sRB + (rgUI[1] ^ 1);
    oFI.className = sRB + (rgUI[2] ^ 1);

    oBBI.src      = sIP + "b" + ((!rgUI[0]) ? sRG : sWT);
    oPBI.src      = sIP + "p" + ((!rgUI[1]) ? sRG : sWT);
    oFBI.src      = sIP + "f" + ((!rgUI[2]) ? sRG : sWT);

    oPlayer.ButtonState = rgUI;
}

function SetNextPrevNavUI(oPlayer)
{
    if(oPlayer.TourNumTotal > 1)
    {
        oPlayer.Tags[cTagNavNextPrev].style.visibility  = 'visible';
        oPlayer.Tags[cTagNavCtrCurrent].innerHTML       = oPlayer.TourNumCurr;
        oPlayer.Tags[cTagNavCtrTotal].innerHTML         = oPlayer.TourNumTotal;

        if(oPlayer.TourNumCurr < oPlayer.TourNumTotal)  //SHOW next link
        {
            try
            {
                var oLnk = GE(oPlayer.ID + '_lnk_' + (oPlayer.TourNumCurr + 1));
                oPlayer.Tags[cTagNavLinkNext].innerHTML     = "<a class=\"BODY1GR2\" href=\"" + oLnk.href + "\">next tour</a>";
            }
            catch(e){}
        }
        else
        {
            oPlayer.Tags[cTagNavLinkNext].innerHTML     = "<span class=\"BODY1GY2\">next tour</span>";
        }

        if(oPlayer.TourNumCurr > 1)                     //SHOW prev link
        {
            try
            {
                var oLnk = GE(oPlayer.ID + '_lnk_' + (oPlayer.TourNumCurr - 1));
                oPlayer.Tags[cTagNavLinkPrev].innerHTML     = "<a class=\"BODY1GR2\" href=\"" + oLnk.href + "\">previous tour</a>";
            }
            catch(e){}
        }
        else
        {
            oPlayer.Tags[cTagNavLinkPrev].innerHTML     = "<span class=\"BODY1GY2\">previous tour</span>";;
        }


    }
    else
    {
        oPlayer.Tags[cTagNavNextPrev].style.visibility  = 'hidden';
    }
}

function SetVTInterval(sCode,iDelay)
{
    ClearVTInterval();
    if(sCode != null) g_oVTInterval = setInterval(sCode,iDelay);
}

function ShowVTour(sMediaID,sImgRef,sDisplayText,iStartPosPcnt,fIs360,sPlayerID,iCount,iCountTotal,iRetries)
{
    //DISREGARD ShowVTour calls that are result of SetTimeout call,
    //          IF a new call to ShowVTour has been initiated after delayed
    //          code set (e.g. user clicked another VTour link while waiting).
    //
    //CAUTION   modifications to tenacity may impact crossbrowser experience in subtle ways.
    if(iRetries == null){g_bTenaciousShow = false;} //RESET tenacity
    else if(g_bTenaciousShow == false){return;}     //ABORT delayed ShowVtour call

    var oVTour;
    var oVTourPlayer;


    //ADD/GET tourplayer to/from dictionary object as appropriate.
    oVTourPlayer = GetVTourPlayer(sPlayerID);

    if(iRetries == null || iRetries <= 2)
    {
        //SET caption and HIGHLIGHT current selected link
        oVTourPlayer.Tags[cTagCaption].innerHTML = sDisplayText;
        oVTourPlayer.HighlightLink(oVTourPlayer.TourNumCurr);
        //SHOW load wait message
        oVTourPlayer.ShowMsg(1,null,true);
    }


    //ADD/GET tour to/from dictionary object as appropriate.
    oVTour   =   GetVTour(sMediaID,sImgRef,sDisplayText,iStartPosPcnt,fIs360);

    if(iCount != null) oVTourPlayer.TourNumCurr         = iCount;
    if(iCountTotal != null) oVTourPlayer.TourNumTotal   = iCountTotal;

    if(oVTourPlayer.IsValid && oVTour.IsValid)
    {
        //LOAD tour
        oVTourPlayer.LoadTour(oVTour);
        //PLAY tour
        oVTourPlayer.PlayCurrent();
    }
    else
    {
        if(!oVTourPlayer.IsValid)
        {
            oVTourPlayer.Report("Player object not valid");
        }
        if(!oVTour.IsValid)
        {
            oVTour.Report("Tour object not valid");
        }

        if(iRetries == null) iRetries = 0;
        if(iRetries < c_iRetryAttemptNum)
        {
            var iDelay = GetTourLoadRetryDelay(iRetries);
            iRetries++;
            g_bTenaciousShow = true;

            setTimeout("ShowVTour("
                        + sMediaID
                        + ",'"  + sImgRef
                        + "','" + sDisplayText
                        + "',"  + iStartPosPcnt
                        + ","   + fIs360
                        + ",'"  + sPlayerID
                        + "',"  + iCount
                        + ","   + iCountTotal
                        + ","   + iRetries
                        + ")"
                        ,iDelay);
        }
        else
        {
            g_bTenaciousShow = false;
            //SHOW load error message
            oVTourPlayer.ShowMsg(2,null,true);
        }
    }
}

function TourPlayerOnLoad(sID)
{
    ClickRemoteLink(sID + "_lnk_1");
    setTimeout("PBID('" + sID + "'," + c_iPlayP + ")",100);
}

////GENERAL HELPER FUNCTIONS : END////


////POSITIONING FUNCTIONS : BEG///

// get the true offset of anything on NS4, IE4/5 & NS6, even if it's in a table!
function getAbsX(element){ return (element.x) ? element.x : getAbsPos(element,"Left"); }
function getAbsY(element){ return (element.y) ? element.y : getAbsPos(element,"Top"); }
function getAbsPos(element,which){iPos = 0;while (element != null){iPos += element["offset" + which];element = element.offsetParent;}return iPos;}

function PositionFloatingPlayer(referenceTag)
{
var windowWidth;
var windowHeight;
var positionX;
var positionY;
var offsetXLeft;
var offsetXRight;
var offsetY;

// find correct offsets
if (referenceTag.tagName.toLowerCase() == 'a') {
    offsetXLeft = c_FloatingPlayerAnchorOffsetXLeft;
    offsetXRight = c_FloatingPlayerAnchorOffsetXRight;
    offsetY = c_FloatingPlayerAnchorOffsetY;
} else if (referenceTag.tagName.toLowerCase() == 'img'){
    offsetXLeft = c_FloatingPlayerImageOffsetXLeft;
    offsetXRight = c_FloatingPlayerImageOffsetXRight;
    offsetY = c_FloatingPlayerImageOffsetY;
}

// obtain window size
if( typeof( window.innerWidth ) == 'number' ) {
    //Non-IE
    windowWidth = window.innerWidth;
    windowHeight = window.innerHeight;
} else if( document.documentElement &&
    ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
    //IE 6+ in 'standards compliant mode'
    windowWidth = document.documentElement.clientWidth;
    windowHeight = document.documentElement.clientHeight;
} else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
    //IE 4 compatible
    windowWidth = document.body.clientWidth;
    windowHeight = document.body.clientHeight;
}

// reference floating player
var playerDiv = GE('VTPlayerFloat');

// calculate X position
if (getAbsX(referenceTag) < (windowWidth / 2))
    positionX = getAbsX(referenceTag) + offsetXLeft;
else
    positionX = getAbsX(referenceTag) + offsetXRight;


// calculate Y position
positionY = getAbsY(referenceTag) + offsetY;

if ((windowHeight < c_FloatingPlayerHeight) || positionY < document.body.scrollTop)
    positionY = document.body.scrollTop;
else if ((positionY + c_FloatingPlayerHeight) > (document.body.scrollTop + document.body.clientHeight))
    positionY = document.body.scrollTop + document.body.clientHeight - c_FloatingPlayerHeight;

// position actual floating player
playerDiv.style.left = positionX;
playerDiv.style.top = positionY;
}

////POSITIONING FUNCTIONS : END///

////////////////////////////////VTOURPLAYER FRAMEWORK : END////////////////////////////////