﻿var lastScriptRefreshCall;
var timeoutRef;
var callNum = 1;
var debugging = false;
var waiting = false;

function refreshScript(url, scriptId)
{
    waiting = true;
    
    var head= document.getElementsByTagName('head')[0];
    var script= document.createElement('script');
    script.id = scriptId;
    script.type = 'text/javascript';
    script.defer = 'defer'; 
    script.src = url;
    head.replaceChild(script, $(scriptId));
    lastScriptRefreshCall = new Date();
    callNum++;
}

function secondsSince(dt)
{
    var now = new Date();
    return (now - dt);
}

function alphaNumericCheck(inputStr)
{
    var regex=/^[0-9A-Za-z]+$/;
    return (regex.test(inputStr));
}

function quoteLoaded(results)
{
    alertMe('about to  set waiting to false from ' + waiting);
    waiting = false;
    
    var numstocks = results.value.items.length;
    alertMe('in callback with numstocks = ' + numstocks);
    
    var resultsIndex = new Array();
    
    for (i=0; i< numstocks; i++)
    {
        var symbol = results.value.items[i].Symbol; 
        symbol = symbol.replace('%2e', '\.');
        var symbolClass = symbol.replace('\.', '');
        
        var price = results.value.items[i].Price;
        var priceTyped = parseFloat(price);
        
        if (priceTyped == 0 || priceTyped == NaN || priceTyped > 500000)
            continue;

        var priceDisplay = priceTyped.toFixed(2);

        var changeAbs = results.value.items[i].Change;
        var changeAbsTyped = parseFloat(changeAbs);
        
        var changePercent = results.value.items[i].ChangePercent;
        
        var volume = results.value.items[i].V;
        var averageVolume = results.value.items[i].AV;
        
        alertMe("updating all symbol: " + symbol);
    
        // we can use dynamically created class names, and we don't ever have to define these classes, but it's useful to be able to select them.  this gets around any issue of ids and duplicates, which is a big big upside.  if we want to style these spans also, we can use multiple css classnames.
        
        var cssClass = "";
        if (changeAbsTyped > 0)
            cssClass = "green";
        else if (changeAbsTyped < 0)
            cssClass = "red";
            
        $$('.price'+symbolClass).each(function(span) {
            // if (parseFloat(span.innerHTML) < parseFloat(price) // etc for some fade effect
            span.innerHTML = priceTyped.toFixed(2);
        });
        
        // change gives the absolute change and percent change in one
        $$('.change'+symbolClass).each(function(span) {
            span.innerHTML = changeAbsTyped.toFixed(2) + " (" + changePercent + ")";                
            appendClass(span, cssClass);
        });
        
        // changeAbs is just absolute change
        $$('.changeAbs'+symbolClass).each(function(span) {
            //alertMe("Found span with content: " + span.innerHTML + " => " + changeAbsTyped.toFixed(2));
            span.innerHTML = changeAbsTyped.toFixed(2);                
            appendClass(span, cssClass);
        });
        
        // changePct is just percent change
        $$('.changePct'+symbolClass).each(function(span) {
            span.innerHTML = changePercent;
            appendClass(span, cssClass);
        });
        
        $$('.gain'+symbolClass).each(function(span) {
            var initPriceStr = span.getAttribute('initiatedPrice');
            var initPrice = parseFloat(initPriceStr);
            var targetPriceStr = span.getAttribute('targetPrice');
            var targetPrice = parseFloat(targetPriceStr);
            
            var closedStr = span.getAttribute('closed');
            
            
            if (closedStr == "False")
            {
                alertMe('updating gain of ' + symbol + ' because it is still open');
                if (!isNaN(initPrice) && !isNaN(targetPrice))
                {
                    var gainPercent;
                    if (targetPrice > initPrice) // long
                    {
                        
                        var gainAbsolute = priceTyped - initPrice;
                        gainPercent = gainAbsolute / initPrice;
                        alertMe('long gain = ' + gainPercent);
                    }
                    else // short
                    {
                        var gainAbsolute = initPrice - priceTyped;
                        gainPercent = gainAbsolute / priceTyped;
                        alertMe('short gain = ' + gainPercent);
                    }
                    
                    if (!isNaN(gainPercent))
                    {
                        span.innerHTML = (gainPercent * 100).toFixed(1) + "%";    
                        if (gainPercent > 0)
                            appendClass(span, 'green');
                        else if (gainPercent < 0)
                            appendClass(span, 'red');
                    }   
                }
            }
        });
        
        if (isHotVolume(volume, averageVolume))
            $$('.hotVolume'+symbol).each(function(span) {
                span.innerHTML = '<img src="/images/PT/tiny-hot.png" title="High volume so far today" alt="volume" />';
            });
     }

    if (numstocks == 0)
        quoteTask(true); // we'll pretend this call didn't happen
    else
    {
        var timeOut = timeout();
        alertMe("setting " + timeOut + " s timeout task");
        timeoutRef = window.setTimeout("quoteTask()", timeOut);
    }
}

function timeout()
{
     if (inMarketHours())
        return 20000;  // 20 sec
    else
        return 60000; // 1 min
}

function appendClass(el, className)
{
    if (el.className.indexOf(className) != -1)
    return;
    
    if (el.className != '')
        el.className += " " + className;
    else
        el.className = className;
}

function quoteTask(firstTime) {
    alertMe("It's been " + secondsSince(lastScriptRefreshCall));
    
    
    var url = 'http://pipes.yahoo.com/pipes/pipe.run?_id=070bb002379a06cca61b6973e053d7e0&_render=json&_callback=quoteLoaded&Symbol=';

    //var symbols = new Array();
    var symbols = "";
    
    if (firstTime === true)
        callNum = 0;
    
    var numSymbols = 0;
    
    $$('.liveSymbol').each(function(span) {
        var symbol = span.innerHTML;
        //symbols.push(symbol); // if array does not already contain
        
        if ((typeof(symbol) != 'function') && symbol.indexOf('^') == -1)
        {
            var symbolCleaned = symbol.replace('\.','%2e').replace('\^', '%5e') + ",";
            if (symbols.indexOf(symbolCleaned) == -1)
                symbols = symbols + symbolCleaned;
            numSymbols++;
        }   
    });
    
    if (numSymbols > 0)
    {
        alertMe('Waiting = ' + waiting);
        if (waiting && callNum > 0)
        {
            alertMe("Still waiting so not making a subsequent call");
            return false;
        }
        else if (callNum > 0 && secondsSince(lastScriptRefreshCall) < timeout())
        {
            alertMe("It hasn't been long enough yet.");
            timeoutRef = window.setTimeout("quoteTask()", timeout());
            return false;
        }
        
        
        var url = url + symbols + '&seq=' + cacheBuster();

        refreshScript(url, 'quoteScriptTag');
        alertMe('in quoteTask refreshing script tag from <a href="' + url + '">' + url + '</a>');
    }
    
}

function cacheBuster()
{
    var myRand=parseInt(Math.random()*99999999);
    return myRand;
}

function alertMe(text)
{
    if (debugging)
        $('output').innerHTML = $('output').innerHTML + text + "<br />";
} 

function isHotVolume(vol, avgvol)
{
    var Now = now();
    var Offset = (Now.Offset <= 0) ? 1 : Now.Offset;
    return (vol > (avgvol * 1.333 * Offset)); 
}

function inMarketHours()
{
    var Now = now();
    return (!(Now.Offset == -1));
}

function now()
{
    var dtNow = new Object();
    var dtDate = new Date();
    dtNow.MarketDay = (dtDate.getDay() != 'Sunday' && dtDate.getDay() != 'Saturday');
    dtNow.Hour = dtDate.getHours();
    dtNow.Minute = dtDate.getMinutes();
    if (!dtNow.MarketDay || dtNow.Hour >= 16 || dtNow.Hour < 9 || (dtNow.Hour == 9 && dtNow.Minute <= 30))
        dtNow.Offset = -1;
    else
        dtNow.Offset = (dtNow.Hour * 60 + dtNow.Minute) / 390 ;
        
    return dtNow;
}

function ajaxDoneQuote()
{
    lastScriptRefreshCall = null;
    quoteTask();
}
