var months = new Array( "Ene", "Feb", "Mar", "Abr", "May", "Jun", "Jul", "Ago", "Sep", "Oct", "Nov", "Dic" );

function OnAbqChange(f)
{
    document.getElementById('SM').value = Round( parseFloat( document.getElementById('CD').value )  + parseFloat( document.getElementById('Abq').value) , 2 ) ;
}

function OnCDChange(f)
{
    document.getElementById('Abq').value = Round( parseFloat( document.getElementById('SM').value ) - parseFloat( document.getElementById('CD').value) , 2 ) ;
}

function OnSMChange(f)
{
    document.getElementById('Abq').value = Round( parseFloat( document.getElementById('SM').value ) - parseFloat( document.getElementById('CD').value) , 2 ) ;
}

function CreateCalcTable( results, iTideDuration, dTideAmplitude, aTideDuration, aTideAmplitude, aIntervals, aCAs )
{
    // Create Data tables
    var iTideDurationIndex = -1, iTideDurationDistance = 10000, iAmplitudeIndex = -1, dAmplitudeDistance = 10000
    var i, j, iTime = 5 * 60, dAmplitude = 0.1, dDistanceAux; 
    // Top rows
    for( i = 0; i < 18; i++ )
    {
        dDistanceAux = Math.abs( iTime - iTideDuration );
        if ( dDistanceAux <= 30 ) 
        {
            if( dDistanceAux < iTideDurationDistance )
            {
                iTideDurationDistance = dDistanceAux;
                iTideDurationIndex = aTideDuration.length;
            }
            aTideDuration[ aTideDuration.length ] = Round( iTime, 2 );
        }
        dDistanceAux = Math.abs( dAmplitude - dTideAmplitude ) ;
        if ( dDistanceAux <= 0.6 )             
        {
            if( dDistanceAux < dAmplitudeDistance )
            {
                dAmplitudeDistance = dDistanceAux;
                iAmplitudeIndex = aTideAmplitude.length;
            }
            aTideAmplitude[ aTideAmplitude.length ] = Round( dAmplitude, 2 );        
        }
        iTime = iTime + 10;
        dAmplitude = dAmplitude + 0.2;
    }

    // iMax is the max number of elements that can be computed, the arrays aTideDuration and aTideAmplitude must have the same size, so the formula can be applied
    // iMax is the max number of elements that can be computed, the arrays aTideDuration and aTideAmplitude must have the same size, so the formula can be applied
    iMax = aTideDuration.length ;
    if ( aTideAmplitude.length < iMax ) 
        iMax = aTideAmplitude.length ;
        
    var bIntervalTable = results[ "Interval" ] > 0 ;
        
    // Intervals table
    var iInertvalIndex = -1, iInertvalDistance = 10000;
    for( i = 0; i < iMax; i++ )
    {
        aIntervals[ i ] = new Array();
        aux = aTideDuration[i] / 30;
        for( j = 1 ; j <= 30; j++ )
        {
            if( results[ "Interval" ] > 0 && i == iTideDurationIndex )
            {
                dDistanceAux = Math.abs( Round( aux * j, 0 ) - results[ "Interval" ] );
                if ( dDistanceAux < iInertvalDistance ) 
                {
                    iInertvalDistance = dDistanceAux;
                    iInertvalIndex = j - 1;
                }                
            }
            aIntervals[ i ][ j - 1 ] = Round( aux * j, 0 );
        }
    }

    // CAs table
    var iCAIndex = -1, dCADistance = 10000;
    for( i = 0; i < iMax; i++ )
    {
        aCAs[ i ] = new Array();
        for( j = 1 ; j <= 30; j++ )
        {
            currValue = Round( 0.5*(aTideAmplitude[i]*(1-Math.cos(aIntervals[ i ][ j - 1 ]*Math.PI/aTideDuration[i]))), 2 );
            if( results[ "CA" ] > 0 && i == iAmplitudeIndex )
            {
                dDistanceAux = Math.abs( currValue - results[ "CA" ] ) ;
                if ( dDistanceAux < dCADistance ) 
                {
                    dCADistance = dDistanceAux;
                    iCAIndex = j - 1;
                }                
            }
            aCAs[ i ][ j - 1 ] = currValue;
        }
    }

    // Create results
    if ( results[ "CA" ] < 0 )
    {
        results[ "CA" ] = new Array();
        results[ "CA" ][ 0 ] = aCAs[ iAmplitudeIndex ][ iInertvalIndex ];
    }
    else
    {
        results[ "Interval" ] = new Array();
        results[ "Interval" ][ 0 ] = aIntervals[ iTideDurationIndex ][ iCAIndex ];
    }
    
    // Create HTML tables
    var iRowType = 0;
    var rowBackGroudColors = new Array ( "", " bgcolor=\"darkgray\" ", " bgcolor=\"gray\" style=\"color:white;\"" );
    time = new TimeCoord();
    s = "<div style='padding:0px 0px 0px 30px    ;'><table><tr><td>";
    // Intervals table
    s = s + "<table style='font-size:10px;text-align:center;' border='1' cellspacing='0'>";    
    s = s + "<tr><td colspan='" + aTideDuration.length + "'>Duraci&oacute;n de la marea (h:mm)</td></tr>";
    s = s + "<tr>";       
    sBgColor = "";    
    for( i = 0 ; i < iMax; i++ )
    {
        if( iTideDurationIndex == i ) 
        {
            sBgColor = " class=\"colorStep1Vertical\" "; sArrow = "&darr;"
        }
        else
        {
            sBgColor = ""; sArrow = ""
        }
        time.minutes = aTideDuration[i];
        s = s + "<td" + sBgColor + ">" + GetHMString(time) + sArrow + "</td>";            
    }
    s = s + "</tr>";                    

    sBgColor = "";        
    s = s + "<tr><td colspan='" + aTideDuration.length + "'>Intervalo desde bajamar m&aacute;s pr&oacute;xima (h:mm)</td></tr>";
    
    for( j = 1 ; j <= 30; j++ )
    {
        s = s + "<tr ";
        if ( iRowType >= rowBackGroudColors.length )
            iRowType = 0;
        s = s + rowBackGroudColors[ iRowType ];
        iRowType = iRowType + 1;
        s = s + ">";    
        for( i = 0; i < iMax; i++ )
        {
            if ( iTideDurationIndex == i && iInertvalIndex == j - 1 ) 
            {
                sBgColor = " class=\"colorStep3Horizontal\" "; sArrow = ""
            }
            else if ( iTideDurationIndex <= i && iInertvalIndex == j - 1 ) 
            {
                sBgColor = " class=\"colorStep3Horizontal\" "; sArrow = "&rarr;"
            }
            else if ( iTideDurationIndex == i && iInertvalIndex >= j - 1 ) 
            {
                sBgColor = " class=\"colorStep1Vertical\" "; sArrow = "&darr;"
            }
            else if ( iTideDurationIndex == i && iCAIndex == j - 1 ) 
            {
                sBgColor = " class=\"colorResult\" "; sArrow = "";
            }
            else if ( iTideDurationIndex <= i && iCAIndex == j - 1 ) 
            {
                sBgColor = " class=\"colorStep3Horizontal\" "; sArrow = "&larr;"
            }
            else if ( iTideDurationIndex == i && iCAIndex >= j - 1 ) 
            {
                sBgColor = " class=\"colorStep1Vertical\" "; sArrow = "&darr;"
            }
            else
            {
                sBgColor = ""; sArrow = "";
            }
            time.minutes = aIntervals[ i ][ j - 1 ];
            s = s + "<td" + sBgColor + ">" + GetHMString( time ) + sArrow + "</td>";    
        }
        s = s + "</tr>";            
    }
    s = s + "</table>";    
    
    // Space
    s = s + "</td><td>&nbsp;</td><td>"; 
    
    // CA table
    s = s + "<table style='font-size:10px;text-align:center;' border='1' cellspacing='0'>";    
    s = s + "<tr><td colspan='" + aTideAmplitude.length + "'>Amplitud de la marea (m)</td></tr>";
    s = s + "<tr>";        
    sBgColor = "";    
    for( i = 0 ; i < iMax; i++ )
    {
        if( iAmplitudeIndex == i ) 
        {
            sBgColor = " class=\"colorStep2Vertical\" "; sArrow = "&darr;";
        }
        else
        {
            sBgColor = ""; sArrow = "";
        }
        s = s + "<td" + sBgColor + ">" + aTideAmplitude[i] + sArrow + "</td>";            
    }
    
    s = s + "<tr><td colspan='" + aTideAmplitude.length + "'>Correcci&oacute;n aditiva (m)</td></tr>";
    iRowType = 0;
    sBgColor = "";    
    for( j = 1 ; j <= 30; j++ )
    {
        s = s + "<tr ";
        if ( iRowType >= rowBackGroudColors.length )
            iRowType = 0;
        s = s + rowBackGroudColors[ iRowType ];
        iRowType = iRowType + 1;
        s = s + ">";    
        for( i = 0; i < iMax; i++ )
        {
            if ( iAmplitudeIndex == i && iCAIndex == j - 1 ) 
            {
                sBgColor = " class=\"colorStep3Horizontal\" "; sArrow = "";
            }
            else if ( iAmplitudeIndex >= i && iCAIndex == j - 1 ) 
            {
                sBgColor = " class=\"colorStep3Horizontal\" "; sArrow = " &larr;";
            }
            else if ( iAmplitudeIndex == i && iCAIndex >= j - 1 ) 
            {            
                sBgColor = " class=\"colorStep2Vertical\" "; sArrow = " &darr;";
            }
            else if ( iAmplitudeIndex == i && iInertvalIndex == j - 1 ) 
            {
                sBgColor = " class=\"colorResult\" "; sArrow = "";
            }
            else if ( iAmplitudeIndex == i && iInertvalIndex >= j - 1 ) 
            {            
                sBgColor = " class=\"colorStep2Vertical\" "; sArrow = " &darr;";
            }
            else if ( iAmplitudeIndex >= i && iInertvalIndex == j - 1 ) 
            {
                sBgColor = " class=\"colorStep3Horizontal\" "; sArrow = " &rarr;";
            }
            else
            {
                sBgColor = "";  sArrow = "";
            }
            s = s + "<td" + sBgColor + ">" + aCAs[ i ][ j - 1 ] + sArrow + "</td>";    
        }
        s = s + "</tr>";            
    }
    s = s + "</table>";    
    
    s = s + "</td></tr></table></div>";
    return s;
}

function GetCorrections( port, corrections )
{
    if ( port == "Sancti-Petri" )
    {
        corrections[ "High" ] = -0.19;
        corrections[ "Low" ] = -0.02;
        corrections[ "HighTime" ] = 5.0;
        corrections[ "LowTime" ] = 5.0;
    }
    else if ( port == "Conil" )  
    {
        corrections[ "High" ] = -0.27;
        corrections[ "Low" ] = -0.05;
        corrections[ "HighTime" ] = -16.0;
        corrections[ "LowTime" ] = -17.0;
    }
    else if ( port == "C. Trafalgar" )
    {
        corrections[ "High" ] = -0.29;
        corrections[ "Low" ] = -0.03;
        corrections[ "HighTime" ] = -20.0;
        corrections[ "LowTime" ] = -20.0;
    }
    else if ( port == "Barbate" )    
    {
        corrections[ "High" ] = -0.80;
        corrections[ "Low" ] = -0.05;
        corrections[ "HighTime" ] = -20.0;
        corrections[ "LowTime" ] = -20.0;
    }
    else if ( port == "Arcila" )
    {
        corrections[ "High" ] = 0.66;
        corrections[ "Low" ] = 0.09;
        corrections[ "HighTime" ] = -5.0;
        corrections[ "LowTime" ] = -5.0;
    }
    else
    {
        corrections[ "High" ] = 0.0;
        corrections[ "Low" ] = 0.0;
        corrections[ "HighTime" ] = 0.0;
        corrections[ "LowTime" ] = 0.0;
    }
}

// This function will return a "coded date" that can be used to compare dates and compute minute differences (using getDateDifference)
// Notice that a month is coded as "(month-1)*1440*31" this means that months that have 28,29 or 30 days will have more than one day
// difference in "coded dates". 
function GetTimeCode( month, day, hour, minute )
{
    return  ( Math.round( month ) - 1 )* 44640 + ( Math.round( day ) - 1 ) * 1440 + Math.round( hour ) * 60 + Math.round( minute );
}

// This function calculates the difference in minutes from date1 and date2.
// This values must be "coded dates" i.e. values returned by the funcion GetDateCode above
// If we do date1-date2 for consecutive days but on different months the result could be greater
// than the correct values. For example, from 30A
function GetTimeDifference( date1, date2 )
{
    ret = date1 - date2;
    if ( ret < 0 )
        ret = -ret;
    while ( ret > 1440 ) 
    {
        ret = ret -1440;
    }
    return ret;
}

function DrawTideHeightsTable( heights, heightindex, spanname )
{
    curday = "";
    if ( heights[0].height > heights[1].height ) 
        lineclass = "tidetablehigh";
    else
        lineclass = "tidetablelow";        
    sLine = "<table class='tidetable'>"
    for ( var i = 0 ; i < heights.length ; i++ )
    {
        if( curday != heights[i].day )
        {
            curday = heights[i].day;
            sLine = sLine + "<tr class='tidetableheader'><td>&nbsp;</td><td colspan='2'>" + curday + " " + months[ heights[i].month - 1 ] + "</td></tr>";
        }
        if( i == heightindex || i == heightindex + 1 )
            sArrow = "&rArr;";
        else
            sArrow = "&nbsp;";

        if ( heights[i].hour < 10 ) 
            sSpace1 = "0";
        else
            sSpace1 = "";        
        if ( heights[i].minute < 10 ) 
            sSpace2 = "0";
        else
            sSpace2 = "";        

        sLine = sLine + "<tr class='" + lineclass + "'><td class='tidetablearrows'>" + sArrow + "</td><td>" + sSpace1 + heights[i].hour + "h" + sSpace2 + heights[i].minute + "'</td><td>" + heights[i].height + "m</td></tr>";
        if ( lineclass == "tidetablehigh" ) 
            lineclass = "tidetablelow";
        else
            lineclass = "tidetablehigh";
    }
    sLine + "</table>";
    document.getElementById(spanname).innerHTML = sLine;"<td >1<td><tr class='tidetablelow'><td>1</td><td>2</td></tr></table>";
}

function GetPressureCorrection( p )
{
    // For some reason, despite "0.05 * Math.round..." is rounded to 2 decimal places
    // sometimes "0.05 - xxx" yields residual decimals; therefore, we 
    // round the whole value to 2 decimal places
    if( p == 0 ) 
        return 0.0; // if p == 0 we don't take it into account  
    else
        return Round( ( 1013 - p ) / 100, 2 ); 
}

function CalcDepth( heights, heightIndex, correction )
{
    // Draw tide tables (not yet)
    //DrawTideHeightsTable( heights, heightIndex, "ResultHeightTable" ) ;

    // Pressure correction
    Pa = document.getElementById('PAmb').value;
    CPa = GetPressureCorrection( Pa );
    sLine = " 1013 &ndash; " + Pa + " = " + Round( CPa * 100, 2 ) + "cm = " + CPa + "m" 
    document.getElementById('ResultPressureCorreccion').innerHTML = sLine;
    // Calado
    CD = document.getElementById('CD').value;
    
    // Get heights and times
    if( heightIndex < 0 || heightIndex >= heights.length - 1 ) 
    {
        document.getElementById('SM').value = "";
        document.getElementById('Abq').value = "";    
        alert( "Error en datos de altura obtenidos del servidor" );
        // Hide Depth Result
        document.getElementById('ResultDepth').style.display = 'none';
        // Hide Time Result
        document.getElementById('ResultTime').style.display = 'none';
        return;
    }

    t1 = GetTimeCode( heights[ heightIndex ].month, heights[ heightIndex ].day, heights[ heightIndex ].hour, heights[ heightIndex ].minute ) ;
    t2 = GetTimeCode( heights[ heightIndex + 1 ].month, heights[ heightIndex + 1 ].day, heights[ heightIndex + 1 ].hour, heights[ heightIndex + 1 ].minute ) ;
    if ( heights[ heightIndex ].height > heights[ heightIndex + 1 ].height )
    {
        HHigh = Round( correction[ "High" ] + Round( heights[ heightIndex ].height, 6 ), 6 );
        HLow = Round( correction[ "Low" ] + Round( heights[ heightIndex + 1 ].height, 6 ), 6 );
        tLow = correction[ "LowTime" ] + t2;
        tHigh = correction[ "HighTime" ] + t1;        
//        t1Str = heights[ heightIndex ].day + " " + months[ heights[ heightIndex ].month - 1 ] + " " + heights[ heightIndex ].hour + "h" + ( correction[ "HighTime" ] + heights[ heightIndex ].minute ) + "'" 
//        t2Str = heights[ heightIndex + 1 ].day + " " + months[ heights[ heightIndex + 1 ].month - 1 ] + " " + heights[ heightIndex + 1 ].hour + "h" + ( correction[ "LowTime" ] + heights[ heightIndex + 1 ].minute ) + "'"     
        t1Str = heights[ heightIndex ].hour + "h" + ( correction[ "HighTime" ] + heights[ heightIndex ].minute ) + "'" 
        t2Str = heights[ heightIndex + 1 ].hour + "h" + ( correction[ "LowTime" ] + heights[ heightIndex + 1 ].minute ) + "'"     
        tLowStr = t2Str;
    }
    else
    {
        HLow = Round( correction[ "Low" ] + Round( heights[ heightIndex ].height, 6 ), 6 );
        HHigh = Round( correction[ "High" ] + Round( heights[ heightIndex + 1 ].height, 6 ), 6 );
        tLow = correction[ "LowTime" ] + t1;   
        tHigh = correction[ "HighTime" ] + t2;                
//        t1Str = heights[ heightIndex ].day + " " + months[ heights[ heightIndex ].month - 1 ] + " " + heights[ heightIndex ].hour + "h" + ( correction[ "LowTime" ] + heights[ heightIndex ].minute ) + "'" 
//        t2Str = heights[ heightIndex + 1 ].day + " " + months[ heights[ heightIndex + 1 ].month - 1 ] + " " + heights[ heightIndex + 1 ].hour + "h" + ( correction[ "HighTime" ] + heights[ heightIndex + 1 ].minute ) + "'"     
        t1Str = heights[ heightIndex ].hour + "h" + ( correction[ "LowTime" ] + heights[ heightIndex ].minute ) + "'" 
        t2Str = heights[ heightIndex + 1 ].hour + "h" + ( correction[ "HighTime" ] + heights[ heightIndex + 1 ].minute ) + "'"     
        tLowStr = t1Str;
    }
   
    tideDuration = new TimeCoord()
    tideDuration.minutes = GetTimeDifference( tHigh, tLow );

    // 2 corrections
    document.getElementById('CorrHigh').innerHTML =  "&#916;t = " + correction[ "HighTime" ] +"'" + ", " + "&#916;H = " + correction[ "High" ] +"m"; 
    document.getElementById('CorrLow').innerHTML =  "&#916;t = " + correction[ "LowTime" ] + "'" + ", " + "&#916;H = " + correction[ "Low" ] +"m"; 
    
    // data from table
    // 3.1 Low tide height
    document.getElementById('ResultBM').innerHTML = HLow;
    // 3.2 Tide duration (hh:mm)
    document.getElementById('ResultD1').innerHTML = t1Str + " &rarr; " + t2Str;
    document.getElementById('ResultD2').innerHTML = GetHMString( tideDuration );   
    // 3.3 Tide height difference
    document.getElementById('ResultAM').innerHTML = HHigh + "m &ndash; " + HLow + "m = " + Round( HHigh - HLow, 2 ) + "m";       
        
    iTargetMonth = 1;//document.getElementById('Month').selectedIndex + 1;
    iTargetDay   = 2;//document.getElementById('Day').value;

    tTargetTime = TimeCoord();
    interval = new TimeCoord()
    GetData( tTargetTime, "Hour", "Min", "", "" );
    
    if( tTargetTime.degrees > heights[ heightIndex + 1 ].hour || 
        ( tTargetTime.degrees == heights[ heightIndex + 1 ].hour && tTargetTime.minutes == heights[ heightIndex + 1 ].minute ) ) 
    {
        iTargetDay = 1;
    }
    
    //t = iTargetDay + " " + months[ iTargetMonth - 1 ] + " " + tTargetTime.degrees + "h" + tTargetTime.seconds / 60 + tTargetTime.minutes + "'";
    t = tTargetTime.degrees + "h" + tTargetTime.seconds / 60 + tTargetTime.minutes + "'";
    interval.minutes = Math.abs( GetTimeDifference( GetTimeCode( iTargetMonth, iTargetDay, tTargetTime.degrees, tTargetTime.seconds / 60 + tTargetTime.minutes ), tLow ) )

    if( interval.minutes > tideDuration.minutes )
    {
        document.getElementById('SM').value = "";
        document.getElementById('Abq').value = "";    
        alert( "Error calculando intervalo. Revise la hora de c&aacute;lculo o las horas del ciclo de marea." ) ;
        // Hide Depth Result
        document.getElementById('ResultDepth').style.display = 'none';
        // Hide Time Result
        document.getElementById('ResultTime').style.display = 'none';
        return;
    }
    // 3.4 Interval to low tide
    document.getElementById('ResultI').innerHTML = t + " &rarr; " + tLowStr + "; I = " + GetHMString( interval ) ;       
        
    if( document.getElementById("CalcTypeTable").checked )
    {
        // Show hide sections
        document.getElementById('CalcTablePanel').style.display = "block";
        document.getElementById('CACalc4').style.display = "block";
        document.getElementById('CACalc4.1').style.display = "none";
        document.getElementById('CACalc4.2').style.display = "none";
                
        // calculate
        aTideDuration = new Array();
        aTideAmplitude = new Array();
        aIntervals = new Array();
        aCAs = new Array();

        results = new Array();
        results[ "CA" ] = -1.0;
        results[ "Interval" ] = interval.minutes;
        document.getElementById('CalcTableA').innerHTML = "&nbsp;&nbsp;&nbsp;" + Round( HHigh - HLow, 2 ) + " m&nbsp;&nbsp;&nbsp;"
        document.getElementById('CalcTableD').innerHTML = "&nbsp;&nbsp;&nbsp;" + GetHMString( tideDuration ) + "&nbsp;&nbsp;&nbsp;";
        document.getElementById('CalcTableI').innerHTML = "&nbsp;&nbsp;&nbsp;" + GetHMString( interval ) + "&nbsp;&nbsp;&nbsp;";
        document.getElementById('CalcTable').innerHTML = CreateCalcTable( results, tideDuration.minutes, HHigh - HLow, aTideDuration, aTideAmplitude, aIntervals, aCAs );
        ca = Round( results[ "CA" ], 2 );
        document.getElementById('ResultCATable').innerHTML = ca ;
    }
    else
    {
        // Show hide sections    
        document.getElementById("CalcTablePanel").style.display = "none";    
        document.getElementById('CACalc4').style.display = "none";
        document.getElementById('CACalc4.1').style.display = "block";
        document.getElementById('CACalc4.2').style.display = "block";

        // calculate        
        // 4.1 alpha
        alpha = interval.minutes * Math.PI / tideDuration.minutes;
        ca = ( HHigh - HLow ) * ( 1 - Math.cos( alpha ) ) / 2;
        document.getElementById('ResultAlpha').innerHTML = Round( alpha * 180 / Math.PI, 6 ) + "&deg;" ;       
        // 4.2 CA
        document.getElementById('ResultCA').innerHTML = Round( ca, 2 ) + "m";       
    }
    
    // SM
    SM = Round( document.getElementById('SC').value, 6 ) +  Round( ca, 6 )  +  Round( CPa, 6 ) +  Round( HLow, 6 ) ;
    SM = Round( SM, 2 );
    //SM = Round( SM, 3 ) ;
    document.getElementById('ResultSM').innerHTML = "<strong>" + SM + "m</strong>";    
    document.getElementById('SM').value = SM;
    
    //Abq
    Abq = SM - Round( CD, 2 );
    Abq = Round( Abq, 2 );
    document.getElementById('ResultAbq').innerHTML = "<strong>" + Abq + "m</strong>";     
    document.getElementById('Abq').value = Abq;    
    
    // Show Depth Result
    a = document.getElementById('ResultDepth');
    a.style.display = 'block';
    // Hide Time Result
    a = document.getElementById('ResultTime');
    a.style.display = 'none';
}

function CalcTime( heights, heightIndex, correction )
{
    // Pressure correction
    Pa = document.getElementById('PAmb').value;
    CPa = GetPressureCorrection( Pa );
    sLine = " 1013 &ndash; " + Pa + " = " + Round( CPa * 100, 2 ) + "cm = " + CPa + "m" 
    document.getElementById('ResultPressureCorreccion_2').innerHTML = sLine;
    // Calado
    CD = document.getElementById('CD').value;
    
    // Get heights and times
    if( heightIndex < 0 || heightIndex >= heights.length - 1 ) 
    {
        document.getElementById('SM').value = "";
        document.getElementById('Abq').value = "";    
        alert( "Error en datos de altura obtenidos del servidor" );
        // Hide Depth Result
        document.getElementById('ResultDepth').style.display = 'none';
        // Hide Time Result
        document.getElementById('ResultTime').style.display = 'none';
        return;
    }

    t1 = GetTimeCode( heights[ heightIndex ].month, heights[ heightIndex ].day, heights[ heightIndex ].hour, heights[ heightIndex ].minute ) ;
    t2 = GetTimeCode( heights[ heightIndex + 1 ].month, heights[ heightIndex + 1 ].day, heights[ heightIndex + 1 ].hour, heights[ heightIndex + 1 ].minute ) ;
    if ( heights[ heightIndex ].height > heights[ heightIndex + 1 ].height )
    {
        iLowTide = -1 ;
        HHigh = Round( correction[ "High" ] + Round( heights[ heightIndex ].height, 6 ), 6 );
        HLow = Round( correction[ "Low" ] + Round( heights[ heightIndex + 1 ].height, 6 ), 6 );
        tLow = correction[ "LowTime" ] + t2;
        tHigh = correction[ "HighTime" ] + t1;   
        tLowMinutes = heights[ heightIndex + 1 ].hour * 60 + heights[ heightIndex + 1 ].minute + correction[ "LowTime" ];
//        t1Str = heights[ heightIndex ].day + " " + months[ heights[ heightIndex ].month - 1 ] + " " + heights[ heightIndex ].hour + "h" + ( correction[ "HighTime" ] + heights[ heightIndex ].minute ) + "'" 
//        t2Str = heights[ heightIndex + 1 ].day + " " + months[ heights[ heightIndex + 1 ].month - 1 ] + " " + heights[ heightIndex + 1 ].hour + "h" + ( correction[ "LowTime" ] + heights[ heightIndex + 1 ].minute ) + "'"     
        t1Str = heights[ heightIndex ].hour + "h" + ( correction[ "HighTime" ] + heights[ heightIndex ].minute ) + "'" 
        t2Str = heights[ heightIndex + 1 ].hour + "h" + ( correction[ "LowTime" ] + heights[ heightIndex + 1 ].minute ) + "'"     
        tLowStr = t2Str;
    }
    else
    {
        iLowTide = 1 ;    
        HLow = Round( correction[ "Low" ] + Round( heights[ heightIndex ].height, 6 ), 6 );
        HHigh = Round( correction[ "High" ] + Round( heights[ heightIndex + 1 ].height, 6 ), 6 );
        tLow = correction[ "LowTime" ] + t1;   
        tHigh = correction[ "HighTime" ] + t2;                
        tLowMinutes = heights[ heightIndex ].hour * 60 + heights[ heightIndex ].minute + correction[ "LowTime" ];        
//        t1Str = heights[ heightIndex ].day + " " + months[ heights[ heightIndex ].month - 1 ] + " " + heights[ heightIndex ].hour + "h" + ( correction[ "LowTime" ] + heights[ heightIndex ].minute ) + "'" 
//        t2Str = heights[ heightIndex + 1 ].day + " " + months[ heights[ heightIndex + 1 ].month - 1 ] + " " + heights[ heightIndex + 1 ].hour + "h" + ( correction[ "HighTime" ] + heights[ heightIndex + 1 ].minute ) + "'"     
        t1Str = heights[ heightIndex ].hour + "h" + ( correction[ "LowTime" ] + heights[ heightIndex ].minute ) + "'" 
        t2Str = heights[ heightIndex + 1 ].hour + "h" + ( correction[ "HighTime" ] + heights[ heightIndex + 1 ].minute ) + "'"     
        tLowStr = t1Str;
    }
   
    tideDuration = new TimeCoord()
    tideDuration.minutes = GetTimeDifference( tHigh, tLow );

    // 2 corrections
    document.getElementById('CorrHigh_2').innerHTML =  "&#916;t = " + correction[ "HighTime" ] +"'" + ", " + "&#916;H = " + correction[ "High" ] +"m"; 
    document.getElementById('CorrLow_2').innerHTML =  "&#916;t = " + correction[ "LowTime" ] + "'" + ", " + "&#916;H = " + correction[ "Low" ] +"m"; 
    
    // data from table
    // 3.1 Low tide height
    document.getElementById('ResultBM_2').innerHTML = HLow;
    // 3.2 Low time time (hh:mm)
    timeLow = new TimeCoord();
    timeLow.minutes = tLowMinutes;
    document.getElementById('ResultHBm_2').innerHTML = GetHMString( timeLow );  

    // 3.3 Tide duration (hh:mm)
    document.getElementById('ResultD1_2').innerHTML = t1Str + " &rarr; " + t2Str;
    document.getElementById('ResultD2_2').innerHTML = GetHMString( tideDuration );   
    // 3.4 Tide height difference
    document.getElementById('ResultAM_2').innerHTML = HHigh + "m &ndash; " + HLow + "m = " + Round( HHigh - HLow, 2 ) + "m";       

    // 4 CA        
    SM = parseFloat( document.getElementById('SM').value );
    SC = parseFloat( document.getElementById('SC').value );    
    CA = SM - HLow - SC - CPa
    document.getElementById('ResultCA_2').innerHTML = Round( CA, 2 ) ;
    
    // 5     
    timeInterval = new TimeCoord();    
    if( document.getElementById("CalcTypeTable").checked )
    {
        // Show hide sections    
        document.getElementById("CalcTablePanel_2").style.display = "block";    
        document.getElementById('ICalc5').style.display = "block";
        document.getElementById('ICalc5.1').style.display = "none";
        document.getElementById('ICalc5.2').style.display = "none";

        // calculate
        aTideDuration = new Array();
        aTideAmplitude = new Array();
        aIntervals = new Array();
        aCAs = new Array();

        results = new Array();
        results[ "Interval" ] = -1.0
        results[ "CA" ] = CA;

        document.getElementById('CalcTableA_2').innerHTML = "&nbsp;&nbsp;&nbsp;" + Round( HHigh - HLow, 2 ) + " m&nbsp;&nbsp;&nbsp;";
        document.getElementById('CalcTableD_2').innerHTML = "&nbsp;&nbsp;&nbsp;" + GetHMString( tideDuration )+ "&nbsp;&nbsp;&nbsp;";
        document.getElementById('CalcTableCA_2').innerHTML = "&nbsp;&nbsp;&nbsp;" +Round( CA, 2 ) + " m&nbsp;&nbsp;&nbsp;";
        document.getElementById('CalcTable_2').innerHTML = CreateCalcTable( results, tideDuration.minutes, HHigh - HLow, aTideDuration, aTideAmplitude, aIntervals, aCAs );

        timeInterval.minutes = Round( results[ "Interval" ], 2 ) ;
        document.getElementById('ResultITable').innerHTML = GetHMString( timeInterval );    
    }
    else
    {
        // Show hide sections    
        document.getElementById("CalcTablePanel_2").style.display = "none";    
        document.getElementById('ICalc5').style.display = "none";
        document.getElementById('ICalc5.1').style.display = "block";
        document.getElementById('ICalc5.2').style.display = "block";

        // calculate     
        // 5.1 alpha
        alpha = Round( Math.acos( 1 - 2 * CA / ( HHigh - HLow ) ) * 180 / Math.PI, 6 ) ;
        document.getElementById('ResultAlpha_2').innerHTML = alpha + "&deg;"
        // 5.1 I
        I = Round( alpha * tideDuration.minutes / 180, 0 ) ; 
        timeInterval.minutes = I ;
        document.getElementById('ResultI_2').innerHTML = GetHMString( timeInterval );    
    }
    
    // 6 Hora
    if( iLowTide > 0 ) 
    {
        document.getElementById('ResultComment_1').style.display = 'none';
        sCommentFlag = ""
        document.getElementById('ResultHSign_2').innerHTML = "+";  
    }
    else
    {
        document.getElementById('ResultComment_1').style.display = 'block';    
        sCommentFlag = " <font color='red'>(*)</font>";
        document.getElementById('ResultHSign_2').innerHTML = "&ndash;";      
    }
    tLowMinutes = tLowMinutes + iLowTide * timeInterval.minutes ;
    if( tLowMinutes < 0 ) 
        tLowMinutes = tLowMinutes + 1440; //if time is negative -> day before Bm 
    if( tLowMinutes > 1440 ) 
        tLowMinutes = tLowMinutes - 1440; //if time > 1 day  -> day after Bm 

    time = new TimeCoord();
    time.minutes = tLowMinutes ;
    document.getElementById('ResultH_2').innerHTML = "<strong>" + GetHMString( time ) + sCommentFlag + "</strong>";        
    RoundDMS( time, 3 );
    document.getElementById('Hour').value = time.degrees;
    document.getElementById('Min').value = time.minutes;    
    // Hide Depth Result
    a = document.getElementById('ResultDepth');
    a.style.display = 'none';
    // Show Time Result
    a = document.getElementById('ResultTime');
    a.style.display = 'block';
}

// --------------------------------------------------------------------
// Ajax functions
// --------------------------------------------------------------------
function AjaxCalcDepth()
{
    /*var xmlHttp = GetHttpRequest();
    if( !xmlHttp )
        return;

    xmlHttp.onreadystatechange=function()
    {

        if(xmlHttp.readyState==4)
        {
            var results = eval('(' + xmlHttp.responseText + ')');
            CalcDepth( results["heights"], results["heightindex"], results["corrections"][0]  );
        }
    }
    url = window.location.href.substr( 0, window.location.href.lastIndexOf('/') ) + "/tideparams.php";
    xmlHttp.open("GET", window.location.href.substr( 0, window.location.href.lastIndexOf('/') ) + "/tideparams.php",true);
    xmlHttp.send(null);*/
    var corrections = new Array();
    var heights = new Array();
    var heights1 = new Array();
    var heights2 = new Array();
    var t1 = TimeCoord(); 
    var t2 = TimeCoord();
    var h1, h2;    
    GetData( t1, "Hour1", "Min1", "", "" );
    GetData( t2, "Hour2", "Min2", "", "" );
    h1 = document.getElementById('Height1').value;
    h2 = document.getElementById('Height2').value;    

    heights1[ "day" ] = "2";
    heights1[ "month" ] = "1";    
    heights1[ "hour" ] = t1.degrees;    
    heights1[ "minute" ] = t1.minutes;
    heights1[ "height" ] = h1;        
    heights2[ "day" ] = "2";
    heights2[ "month" ] = "1";    
    heights2[ "hour" ] = t2.degrees;    
    heights2[ "minute" ] = t2.minutes;
    heights2[ "height" ] = h2;        
 
    if ( t1.degrees > t2.degrees || ( t1.degrees == t2.degrees && t1.minutes > t2.minutes ) ) 
        heights1[ "day" ] = "1";    
        
    heights[0]=heights1;
    heights[1]=heights2;    
    
    sPortName = document.getElementById('Puerto').value;
    if ( sPortName == "" )  // for IExplorer 7
        sPortName = document.getElementById('Puerto').options[ document.getElementById('Puerto').selectedIndex ].text;
    GetCorrections( sPortName, corrections ) ;
 
    CalcDepth( heights, 0, corrections );    

}

function AjaxCalcTime()
{
/*    var xmlHttp = GetHttpRequest();
    if( !xmlHttp )
        return;

    xmlHttp.onreadystatechange=function()
    {

        if(xmlHttp.readyState==4)
        {
            var results = eval('(' + xmlHttp.responseText + ')');
            CalcTime( results["heights"], results["heightindex"], results["corrections"][0] );
        }
    }
    url = window.location.href.substr( 0, window.location.href.lastIndexOf('/') ) + "/tideparams.php";
    xmlHttp.open("GET", window.location.href.substr( 0, window.location.href.lastIndexOf('/') ) + "/tideparams.php",false);
    xmlHttp.send(null);
    var the_object = eval("(" + xmlHttp.responseText + ")");
    alert( the_object.heights[0]["day"]);        */ 
            
    var corrections = new Array();
    var heights = new Array();
    var heights1 = new Array();
    var heights2 = new Array();
    var t1 = TimeCoord(); 
    var t2 = TimeCoord();
    var h1, h2;    
    GetData( t1, "Hour1", "Min1", "", "" );
    GetData( t2, "Hour2", "Min2", "", "" );
    h1 = document.getElementById('Height1').value;
    h2 = document.getElementById('Height2').value;    

    heights1[ "day" ] = "2";
    heights1[ "month" ] = "1";    
    heights1[ "hour" ] = t1.degrees;    
    heights1[ "minute" ] = t1.minutes;
    heights1[ "height" ] = h1;        
    heights2[ "day" ] = "2";
    heights2[ "month" ] = "1";    
    heights2[ "hour" ] = t2.degrees;    
    heights2[ "minute" ] = t2.minutes;
    heights2[ "height" ] = h2;        
 
    if ( t1.degrees > t2.degrees || ( t1.degrees == t2.degrees && t1.minutes > t2.minutes ) ) 
        heights1[ "day" ] = "1";    
        
    heights[0]=heights1;
    heights[1]=heights2;    
    
    sPortName = document.getElementById('Puerto').value;
    if ( sPortName == "" )  // for IExplorer 7
        sPortName = document.getElementById('Puerto').options[ document.getElementById('Puerto').selectedIndex ].text;
    GetCorrections( sPortName, corrections ) ;
 
    CalcTime( heights, 0, corrections );    
    
}