var map = null;
var geocoder = null;
var khand = null;
var _mode = 'd';  // can be d, dm, dgs

function dec2sexa(num) 
{
    var r = Math.floor(num);
    if (num < 0) { r = r + 1; }
    return [r, Math.abs(num - r) * 60];
}

// Convert radian angle to degrees
function radToDeg(angleRad) 
{
    return (180.0 * angleRad / Math.PI);
}


// Convert degree angle to radians
function degToRad(angleDeg) 
{
    return (Math.PI * angleDeg / 180.0);
}

// Name:    calcJD
// Purpose: Julian day from calendar day
// Arguments:
//   year : 4 digit year
//   month: January = 1
//   day  : 1 - 31
// Return value:
//   The Julian day corresponding to the date
// Note:
//   Number is returned for start of day.  Fractional days should be
//   added later.
function calcJD(year, month, day)
{
    if (month <= 2) {
        year -= 1;
        month += 12;
    }
    var A = Math.floor(year/100);
    var B = 2 - A + Math.floor(A/4);
    
    var JD = Math.floor(365.25*(year + 4716)) + 
        Math.floor(30.6001*(month+1)) + day + B - 1524.5;
    return JD;
}

// Name:    calcTimeJulianCent
// Purpose: convert Julian Day to centuries since J2000.0
// Arguments:
//   jd : the Julian Day to convert
// Return value:
//   the T value corresponding to the Julian Day
function calcTimeJulianCent(jd)
{
    var T = (jd - 2451545.0)/36525.0;
    return T;
}

// Name:    calGeomMeanLongSun
// Purpose: calculate the Geometric Mean Longitude of the Sun
// Arguments:
//   t : number of Julian centuries since J2000.0
// Return value:
//   the Geometric Mean Longitude of the Sun in degrees
function calcGeomMeanLongSun(t)
{
    var L0 = 280.46646 + t * (36000.76983 + 0.0003032 * t);
    while(L0 > 360.0)
    {
        L0 -= 360.0;
    }
    while(L0 < 0.0)
    {
        L0 += 360.0;
    }
    return L0;      // in degrees
}

// Name:    calGeomAnomalySun
// Purpose: calculate the Geometric Mean Anomaly of the Sun
// Arguments:
//   t : number of Julian centuries since J2000.0
// Return value:
//   the Geometric Mean Anomaly of the Sun in degrees
function calcGeomMeanAnomalySun(t)
{
    var M = 357.52911 + t * (35999.05029 - 0.0001537 * t);
    return M;       // in degrees
}

// Name:    calcSunEqOfCenter
// Purpose: calculate the equation of center for the sun
// Arguments:
//   t : number of Julian centuries since J2000.0
// Return value:
//   in degrees
function calcSunEqOfCenter(t)
{
    var m = calcGeomMeanAnomalySun(t);

    var mrad = degToRad(m);
    var sinm = Math.sin(mrad);
    var sin2m = Math.sin(mrad+mrad);
    var sin3m = Math.sin(mrad+mrad+mrad);
    
    var C = sinm * (1.914602 - t * (0.004817 + 0.000014 * t)) + 
        sin2m * (0.019993 - 0.000101 * t) + sin3m * 0.000289;
    return C;       // in degrees
}

// Name:    calcSunTrueLong
// Purpose: calculate the true longitude of the sun
// Arguments:
//   t : number of Julian centuries since J2000.0
// Return value:
//   sun's true longitude in degrees
function calcSunTrueLong(t)
{
    var l0 = calcGeomMeanLongSun(t);
    var c = calcSunEqOfCenter(t);
    
    var O = l0 + c;
    return O;       // in degrees
}

// Name:    calcSunApparentLong
// Purpose: calculate the apparent longitude of the sun
// Arguments:
//   t : number of Julian centuries since J2000.0
// Return value:
//   sun's apparent longitude in degrees
function calcSunApparentLong(t)
{
    var o = calcSunTrueLong(t);
    
    var omega = 125.04 - 1934.136 * t;
    var lambda = o - 0.00569 - 0.00478 * Math.sin(degToRad(omega));
    return lambda;      // in degrees
}

// Name:    calcMeanObliquityOfEcliptic
// Purpose: calculate the mean obliquity of the ecliptic
// Arguments:
//   t : number of Julian centuries since J2000.0
// Return value:
//   mean obliquity in degrees
function calcMeanObliquityOfEcliptic(t)
{
    var seconds = 21.448 - t*(46.8150 + t*(0.00059 - t*(0.001813)));
    var e0 = 23.0 + (26.0 + (seconds/60.0))/60.0;
    return e0;      // in degrees
}

// Name:    calcObliquityCorrection
// Purpose: calculate the corrected obliquity of the ecliptic
// Arguments:
//   t : number of Julian centuries since J2000.0
// Return value:
//   corrected obliquity in degrees
function calcObliquityCorrection(t)
{
    var e0 = calcMeanObliquityOfEcliptic(t);
    
    var omega = 125.04 - 1934.136 * t;
    var e = e0 + 0.00256 * Math.cos(degToRad(omega));
    return e;       // in degrees
}

// Name:    calcSunDeclination
// Purpose: calculate the declination of the sun
// Arguments:
//   t : number of Julian centuries since J2000.0
// Return value:
//   sun's declination in degrees
function calcSunDeclination(t)
{
    var e = calcObliquityCorrection(t);
    var lambda = calcSunApparentLong(t);

    var sint = Math.sin(degToRad(e)) * Math.sin(degToRad(lambda));
    return radToDeg(Math.asin(sint));
}

// Name:    calcSunRtAscension
// Purpose: calculate the right ascension of the sun
// Arguments:
//   t : number of Julian centuries since J2000.0
// Return value:
//   sun's right ascension in degrees
function calcSunRtAscension(t)
{
    var e = calcObliquityCorrection(t);
    var lambda = calcSunApparentLong(t);
 
    var tananum = (Math.cos(degToRad(e)) * Math.sin(degToRad(lambda)));
    var tanadenom = (Math.cos(degToRad(lambda)));
    return radToDeg(Math.atan2(tananum, tanadenom));
}

// Name:    calcDayOfYear
// Purpose: Finds numerical day-of-year from mn, day and lp year info
// Arguments:
//   year
//   month: January = 1
//   day  : 1 - 31
// Return value:
//   The numerical day of year
function calcDayOfYear(year, month, day) 
{
    var N1 = Math.floor(275. * month / 9.0);
	var N2 = Math.floor((month + 9.0) / 12.0);
	var N3 = (1. + Math.floor((year - 4 * Math.floor(year / 4.) + 2) / 3.));
	return N1 - (N2 * N3) + day - 30;
}

function normTime(t) 
{
    if (t < 0) { t = t+24; }
    if (t >= 24) { t = t-24; }
    return t;
}

// ln in hours
function localMeanTime(H, ra, t, ln)
{
    return normTime(H + ra - (0.06571 * t) - 6.622 - ln);
}

function sun(lt, ln, year, month, day) 
{
    var T = calcTimeJulianCent(calcJD(year, month, day));
    var dec = degToRad(calcSunDeclination(T));
    var ra = calcSunRtAscension(T) / 15.; //hours
    lt = degToRad(lt);

    // Sun's local hour angle
    var cosH = (Math.cos(degToRad(90.833)) - Math.sin(dec)*Math.sin(lt)) /
        (Math.cos(dec)*Math.cos(lt));

    var lnHour = ln/15.0;
    var doy = calcDayOfYear(year, month, day);

    var times = {};
    if (cosH >= -1) {
        var Hset = radToDeg(Math.acos(cosH));
        times['set'] = localMeanTime(Hset/15., ra, doy + (18 - lnHour)/24., 
                                       lnHour);
    }
    if (cosH <= 1) {
        var Hrise = 360 - Hset;
        times['rise'] = localMeanTime(Hrise/15., ra, doy + (6 - lnHour)/24., 
                                      lnHour);
    }
    return times;
}

// rise 7:54, set 17:37
// 42 43.4974, -8 28.8867

// rise 13:11 set 19:39
// 63 53.0729, -63 16.8750

function toHMin (t,date) 
{
    var h = Math.floor(t);
    var m = Math.floor(60. * (t - h)) + '';
    
    if (h<0) {
    	h=24+h;
    }
    
    var s=date.getTimezoneOffset();
    
    if (s==-120) {
    	h++;
    }
    
    if (m.length == 1) { m = '0' + m; }
    return h + ':' + m;
}

function getSelectedDate() 
{
    var dtext = document.getElementById('dData');
    dTextValue=dtext.value;
    dTextValue = dTextValue.replace(/\//gi, '-');
    var df = dTextValue.split('-');
    
    var d=new Date();

    var month=parseInt(df[1]-1);
    var year=parseInt(df[2]);
    
    d.setMonth(month);
    d.setDate(df[0]);
    d.setFullYear(year);
    return d;
}

function reportPointCoords() 
{
        var lt = 39.443484;
        var ltgm = dec2sexa(lt);
        var ltms = dec2sexa(ltgm[1]);

        var ln = 2.7671814;
        var lngm = dec2sexa(ln);
        var lnms = dec2sexa(lngm[1]);

        var date = getSelectedDate();

        var times = sun(lt, ln, 
            date.getFullYear(), date.getMonth()+1, date.getDate());
        var tset = '(no se pone)';
        if (times['set']) {
            tset = toHMin(times['set'],date);
        }
        var trise = '(no sale)';
        if (times['rise']) {
            trise = toHMin(times['rise'],date);
        }

        // One second is around 30m, so for a precision of at least 1m
        // we need 0.03 s, 0.0005 m, or 9.2e-6 dg. 
		/*
        var latlong = "<font color='blue'>lat, long</font><font size='-1'>";
        if (_mode == 'd') {
            latlong += (' (grad):</font><br/>&nbsp;&nbsp;&nbsp;' + 
                        lt.toPrecision(8) + ", " + 
                        ln.toPrecision(8));
        }
        if (_mode == 'dm') {
            latlong += (' (grad min)</font><br/>&nbsp;&nbsp;&nbsp;' +
                        ltgm[0] + " " + 
                        ltgm[1].toPrecision(6) + ", " + 
                        lngm[0] + " " + 
                        lngm[1].toPrecision(6));
        }
        if (_mode == 'dms') {
            latlong += (' (grad min seg)</font><br/>&nbsp;&nbsp;&nbsp;' +
                        ltgm[0] + " " + ltms[0] + " " + 
                        ltms[1].toPrecision(5) + ", " + 
                        lngm[0] + " " + lnms[0] + " " + 
                        lnms[1].toPrecision(5));
        }
        */
        return tset;
        //alert('Raise: '+trise+' Set: '+tset);
        
        /*
        map.openInfoWindowHtml(point,
                               latlong + "<br/><font color='blue'>sol</font> <font size='-1'>(hora <a href='http://es.wikipedia.org/wiki/Tiempo_universal_coordinado'>UTC</a>):</font>"+
                               "<br/>&nbsp;&nbsp;&nbsp;salida: " + trise +
                               "<br/>&nbsp;&nbsp;&nbsp;puesta: " + tset
                              );
        */
}