

var logData = '';
var logCount = 0;

function rad2deg(radians) {
  degrees = radians * (180/Math.PI);
  return Math.round(degrees);
}

function moonphase(date,size,lat,black,white) {

  var html = '<p>This is the Northern Hemisphere moon on ' + date.toString('dddd, MMMM ,yyyy') + ':</p>';
  html += '<div style="width:100px:margin:auto">';
  html += '<p class="moon">';
  html += moonIMG(date,size,1);
  html += '</p>';
  html += '</div>';
  html += '<p>';
  html += 'and this is the Southern Hemisphere moon</p><p class="moon">';
  html += moonIMG(date,size,-1);
  html += '</p><p>' +
  ( fullmoon===0 ? 'It is full moon..' :
   ( fullmoon===1 ? 'Tomorrow is the next full moon' :
    'The next full moon in the Northern Hemisphere will be in ' + fullmoon + ' days time' ) ) + '.</p>' ;

  document.getElementById('moon' ).innerHTML = html;

}

var fullmoon;

function moonHTML(date,size,lat,black,white,width){
  if (typeof width == 'undefined') width = 100;
  var html = '';
  html += '<div style="width:'+width+'px:margin:auto">';
  //html += '<table align="center" cellpadding="0" cellspacing="0"><tr><td align="center">';
  html += moonIMG(date,size,lat,black,white);
  //html += '</td></tr></table>';
  html += '</div>';
  return html;
}

function moonIMG(date,size,lat,black,white){
 if (typeof size == 'undefined') size = 30;
 if (typeof black == 'undefined') black = "trans.gif";
 if (typeof white == 'undefined') white = "white.gif";
 date.setTime( date.getTime() + date.getTimezoneOffset() * 60000 );
 var aspectRatio = 4/3,
  i, m, width,
  html = '',
  bluemoon = new Date( 96, 1, 3, 16, 15, 0 ),
  lunarperiod = 29 * ( 24 * 3600 * 1000 ) + 12 * ( 3600 * 1000 ) + 44.05 * ( 60 * 1000 ),
  phasetime = ( date.getTime() - bluemoon.getTime() ) % lunarperiod,
  fraction = phasetime / lunarperiod,
  left, right,
  percent = Math.round( 200 * fraction ) % 100;
  if (lat < 0) {
    var temp = black;
    black = white;
    white = temp;
  }
  left  = fraction >= 0.5 ? black : white;
  right = fraction >= 0.5 ? white : black;
 fullmoon = Math.round( ( lunarperiod - phasetime ) / ( 24 * 3600 * 1000 ) );

 for( i = -(size-1); i < size; ++i ) {
  width = aspectRatio * 2 * parseFloat( Math.sqrt( size * size - i * i ) ) / 100;
  html += '<div class="moonline">';
  if( percent!==100 ) {
   html += '<img src="' + left + '" width="' + Math.round( width * ( 100 - percent ) ) + '" height="1"/>';
  }
  if( percent!==0 ) {
   html += '<img src="' + right + '" width="' + Math.round( width * percent ) + '" height="1"/>' ;
  }
  html += '</div>' ;
 }
 return html;
}

function moonPhaseNames(phase){
var names = "New\tWaxing Crescent\tFirst Quarter\tWaxing Gibbous\t";
    names += "Full\tWaning Gibbous\tThird Quarter\tWaning Crescent";
    names = names.split("\t");
    return names[phase];
}


function moonCanvas(date,left,top,size,lat,opacity,canvasID,background){

// using http://paulburke.net/geometry/2circle and Tim Voght's c code

function circles(x0, y0, r0, x1, y1, r1) {
  logData += 'I x0='+x0+' y0='+y0+' r0='+r0+' x1='+x1+' y1='+y1+' r1='+r1+' <br/>'+"\n";

  var a, dx, dy, d, h, rx, ry, x2, y2;
  var retval = {rc:true,xi0:0,yi0:0,xi1:0,yi1:0,rad0:0,rad1:0};

  /* dx and dy are the vertical and horizontal distances between
   * the circle centers.
   */
  dx = x1 - x0;
  dy = y1 - y0;

  /* Determine the straight-line distance between the centers. */
  d = Math.sqrt((dy*dy) + (dx*dx));

  /* Check for solvability. */
  if (d > (r0 + r1))
  {
    /* no solution. circles do not intersect. */
    retval.rc = false;
    //return retval;
  }
  if (d < Math.abs(r0 - r1))
  {
    /* no solution. one circle is contained in the other */
    retval.rc = false;
    //return retval;
  }

  /* 'point 2' is the point where the line through the circle
   * intersection points crosses the line between the circle
   * centers.
   */

  /* Determine the distance from point 0 to point 2. */
  a = ((r0*r0) - (r1*r1) + (d*d)) / (2.0 * d) ;

  /* Determine the coordinates of point 2. */
  x2 = x0 + (dx * a/d);
  y2 = y0 + (dy * a/d);

  /* Determine the distance from point 2 to either of the
   * intersection points.
   */
  h = Math.sqrt((r0*r0) - (a*a));

  /* Now determine the offsets of the intersection points from
   * point 2.
   */
  rx = -dy * (h/d);
  ry = dx * (h/d);

  /* Determine the absolute intersection points. */
  retval.xi0 = x2 + rx;
  retval.xi1 = x2 - rx;
  retval.yi0 = y2 + ry;
  retval.yi1 = y2 - ry;

  /* calculate the radians = (Math.PI/180)*degrees; */
  retval.rad0 = Math.asin(h/r0);
  retval.rad1 = Math.asin(h/r1);
  logData += 'I h='+h+' xi0='+retval.xi0+' yi0='+retval.yi0+' xi1='+retval.xi1+' yi1='+retval.yi1+' rad0='+retval.rad0+' rad1='+retval.rad1+' h='+h+' <br/>'+"\n";
  if (debug) {
    drawCircle(ctx,x0,y0,r0);
    drawCircle(ctx,x1,y1,r1,1,'red');
    drawLine(ctx,retval.xi0,retval.yi0,retval.xi1,retval.yi1,'blue');
    drawLine(ctx,x0,y0,retval.xi0,retval.yi0,'blue');
    drawLine(ctx,x0,y0,retval.xi1,retval.yi1,'blue');
    drawLine(ctx,x1,y1,retval.xi0,retval.yi0,'blue');
    drawLine(ctx,x1,y1,retval.xi1,retval.yi1,'blue');
  }
  return retval;
}


 function arc2radius(w,h) {
   return (h/2)+((w*w)/(8*h));
 }

 function drawMoon(ctx,x,y,radius,arcHeight,left,lat,phase){
   var name = moonPhaseNames(phase);
   var crescent = (name.indexOf('Crescent') > -1);
   var quarter = (name.indexOf('Quarter') > -1);
   if (!crescent) crescent = quarter;

   if (arcHeight == 0) {
     radius1 = 0;
   } else
   if (arcHeight > 0) {
   var radius1 = arc2radius(2*radius,arcHeight); // Arc radius
   var x1 = x+(radius+arcHeight)-radius1;
   if (lat < 0) x1 = x+ (radius - arcHeight) + radius1;
   } else
   if ( arcHeight < 0 ){
     radius1 = arc2radius(2*radius,Math.abs(arcHeight));
     x1 = x+ (radius + arcHeight) + radius1;
     if (lat < 0) {
       x1 = x+(radius-arcHeight)-radius1;
     }
   }
   logData += 'D  x='+x+' y='+y+' x1='+x1+' radius='+radius+' arcHeight='+arcHeight+' left='+left+' radius1='+radius1+' lat='+lat+' phase='+phase+' name='+name+'<br/>'+"\n";
   if (arcHeight == 0) {
   }  else
   var intersection = circles(x+radius,y+radius,radius,x1,y+radius,radius1);
   if (Math.round(radius1) == radius) {
     logData += 'Same radius<br>';
     if (phase ==  0 ) {
       drawCircle(ctx,x+radius,y+radius,radius,1,'white');
     } else {
       drawCircle(ctx,x+radius,y+radius,radius,0,'white');
     }
     return;
   }
   ctx.fillStyle = 'white';
   var north = Math.PI*3/2,
       west = Math.PI,
       south = Math.PI/2;
   /*
   if (lat < 0) {
     south = Math.PI*3/2;
     north = Math.PI/2;
     west = 0;
   }
   rotate = (lat > 0)?0:Math.PI;
   */
   rotate = 0;
   var cWise = left;

   //if (lat < 0) left = !left;
   ctx.strokeStyle = ctx.fillStyle;
   // copied from http:developer.mozilla.org/samples/canvas-tutorial/2_4_canvas_arc.html
   ctx.beginPath();
   var X          = x+radius;                // x coordinate
   var Y          = y+radius;                // y coordinate
// var radius     = size;                  // Arc radius
   var startAngle = north+rotate;                 // Starting point on circle
   var endAngle   = south+rotate;                 // End point on circle
   var clockwise  = (lat>0)?left:!left;          // clockwise or anticlockwise
   clockwise =   cWise;

   if (lat < 0) {
       endAngle += (endAngle < Math.PI)?Math.PI:-Math.PI;
       startAngle += (startAngle < Math.PI)?Math.PI:-Math.PI;
   }
   ctx.arc(X,Y,radius,startAngle,endAngle, clockwise);
   logData += 'C X='+X+' Y='+Y+' radius='+radius+ ' startAngle='+rad2deg(startAngle)+' endAngle='+rad2deg(endAngle)+' clockwise='+clockwise+'<br/>'+"\n";
   if (left && (arcHeight > 0)) {
      ctx.fill();
   }
   if (arcHeight != 0) {
   if (debug) ctx.fillStyle='#FF0000';
   //ctx.beginPath();

   var aRadius    = radius1; // Arc radius
   var X          = x1;                // x coordinate
   var Y          = y+radius;                // y coordinate
   if (arcHeight < 0) {
     var startAngle = (west-intersection.rad1)+rotate;       // Starting point on circle
     var endAngle =   ((2*Math.PI) - startAngle)+rotate;       // End point on circle
     var clockwise  = !cWise;                 // clockwise or anticlockwise
   } else {
     var startAngle = intersection.rad1+rotate;       // Starting point on circle
     var endAngle   = ((2*Math.PI)-intersection.rad1)+rotate;       // End point on circle
     var clockwise  = left;              // clockwise or anticlockwise
   }
   if (lat < 0) {
       endAngle += (endAngle < Math.PI)?Math.PI:-Math.PI;
       startAngle += (startAngle < Math.PI)?Math.PI:-Math.PI;
   }

   clockwise = (crescent)?!cWise:cWise;
   if ((arcHeight > 0) && (phase == 2)) {
      clockwise = cWise;
   }
   if ((arcHeight < 0) && (phase == 6)) {
      clockwise = cWise;
   }

   ctx.arc(X,Y,aRadius,startAngle,endAngle, clockwise);
   ctx.strokeStyle = 'yellow';
   logData += 'A X='+X+' Y='+Y+' radius='+aRadius+ ' startAngle='+rad2deg(startAngle)+ ' endAngle='+rad2deg(endAngle)+' clockwise='+clockwise+'<br/>'+"\n";
   ctx.fill();
   if (debug) {
     ctx.strokeStyle = 'yellow';
     ctx.stroke();
   }

   } else {
      ctx.fill();
   }
   if (debug) {
     if (arcHeight != 0) {
        ctx.strokeStyle = '#0000FF';
        ctx.beginPath();
        ctx.moveTo(intersection.xi0,intersection.yi0);
        ctx.lineTo(intersection.xi1,intersection.yi1);
        ctx.stroke();
     }
   }
 }

 function drawLine(ctx,x0,y0,x1,y1,fill,w) {
   if (typeof fill != 'undefined') ctx.fillStyle = fill;
   if (typeof y1 == 'undefined') {
      x1 = x0+x1;
      y1 = y0;
    }
    ctx.strokeStyle = ctx.fillStyle;
    ctx.lineWidth = w;
    ctx.beginPath();
    ctx.moveTo(x0,y0);
    ctx.lineTo(x1,y1);
    ctx.closePath();
    ctx.stroke();
 }

 function drawCircle(ctx,x,y,r,line,fill) {
   ctx.strokeStyle = ctx.fillStyle;
   if (typeof fill != 'undefined') ctx.fillStyle = fill;

   ctx.strokeStyle = ctx.fillStyle;
   // copied from http:developer.mozilla.org/samples/canvas-tutorial/2_4_canvas_arc.html
   i = 0;
   var j = 2;
   ctx.beginPath();
   var X          = x;                // x coordinate
   var Y          = y;                // y coordinate
   var radius     = r;                  // Arc radius
   var startAngle = 0;                     // Starting point on circle
   var endAngle   = Math.PI+(Math.PI*j)/2; // End point on circle
   var clockwise  = i%2==0 ? false : true; // clockwise or anticlockwise

   ctx.arc(X,Y,radius,startAngle,endAngle, clockwise);

   if (line==0){
      ctx.fill();
   } else {
     if (typeof line != 'undefined') ctx.lineWidth = line;
     ctx.stroke();
   }
 }

 if (typeof canvasID == 'undefined') canvasID = 'canvas';
 if (typeof x == 'undefined') x = 0;
 if (typeof y == 'undefined') y = 0;
 if (typeof opacity == 'undefined') opacity = 1;
 if (typeof lat == 'undefined') lat = 1;

 var c = document.getElementById(canvasID);
 if (c==null) {
    alert ('No canvas element defined');
    return;
 }
 if (!c.getContext){
    alert ('To use this you need to change your browser to a more modern one.');
    return;
 }

 var debug = false;
 var debugLog = document.getElementById('debugLog');
 if (debugLog) {
    if (getParam('debug')) {
        debug = true;
        debugLog.style.display == '';
    }
 }
 var ctx=c.getContext("2d");
 var car = c.offsetHeight/c.offsetWidth;

 date.setTime( date.getTime() + date.getTimezoneOffset() * 60000 );
 var x = left;
 var y = top;
 var aspectRatio = (car > 0.5)?1:0.5,
  i, m, width,
  html = '',
  bluemoon = new Date( 96, 1, 3, 16, 15, 0 ),
  lunarperiod = 29 * ( 24 * 3600 * 1000 ) + 12 * ( 3600 * 1000 ) + 44.05 * ( 60 * 1000 ),
  phasetime = ( date.getTime() - bluemoon.getTime() ) % lunarperiod,
  fraction = phasetime / lunarperiod,
  left, right,
  black = 'black',
  white = 'white',
  newmoon = true,
  percent = Math.round( 200 * fraction ) % 100;
  /*
  if (lat < 0) {
    var temp = black;
    black = white;
    white = temp;
  }
  */
  left  = fraction >= 0.5 ? black : white;
  right = fraction >= 0.5 ? white : black;
  fullmoon = Math.round( ( lunarperiod - phasetime ) / ( 24 * 3600 * 1000 ) );
  var moonPhases = new Array(4,4,4,5,5,5,5,6,6,6,7,7,7,7,0,0,0,1,1,1,1,2,2,2,3,3,3,3,4,4,4);
  var moonPhase = moonPhases[fullmoon];
 logData += 'M date='+date.toString()+' fullmoon='+fullmoon+' percent='+percent+' fraction='+fraction+' AspectRatio='+aspectRatio+'<br/>'+"\n";
 if (typeof background == 'array') {
    ctx.fillStyle = "rgb("+background[0]+","+background[1],+","+background[2]+")";
    ctx.fillRect (x, y, aspectRatio*2*size, 2*size);
 }
 ctx.fillStyle = "rgba(255,255,255,"+opacity+")";
 var row = 0;
 for( i = -(size-1); i < size; ++i ) {
  if (moonPhase == 0) {
    newmoon = true;
    break;
  }
  width = 2 * parseFloat( Math.sqrt( size * size - i * i ) ) / 100;
   var indent = Math.round(aspectRatio*((2*size)-(width*100))/2);
   var w = Math.round(width*100);
   if( percent!==100 ) {
   var lw = Math.round( aspectRatio * width * ( 100 - percent ) );
   if (left == 'white') {
    if (i == 0) {
    r = size*(7+fullmoon-28)/7;
    r = lw-size;
    logData += 'L width='+w+' x='+x+' i='+indent+' y='+(y+row)+' w='+lw+' r='+r+'<br/>'+"\n";
    drawLeft = true;
    drawMoon(ctx,x,y,size,r,drawLeft,lat,moonPhase);
    break;
    }
    newmoon = false;
   } else {
     indent+=lw;
   }
  }
  if( percent!==0 ) {
   var rw = Math.round( aspectRatio * width * percent );
   if (right == 'white') {
    if (i == 0) {
       var l = indent-size;
       //l = size*(7+fullmoon-28)/7;
       logData += 'R width='+w+' x='+' i='+indent+' y='+(y+row)+' w='+rw+' l='+l+'<br/>'+"\n";
       drawLeft = false;
       drawMoon(ctx,x,y,size,l,drawLeft,lat,moonPhase);
       break;
    }
    newmoon = false;
   }
  }
  row++
 }
 if (newmoon) {
   logData += 'New Moon';
   drawCircle(ctx,x+size,y+size,size,1,'white');
 }

 logCount++;
 if (debug) debugLog.innerHTML = logCount+': '+logData+'<br>'+debugLog.innerHTML;
 logData = '';
 return (moonPhase);
}

function moonloop( n ) {
  var t = new Date();
  t.setTime( t.getTime() + 86400000 * n );
  moonphase( t );
  window.setTimeout( 'moonloop(' + (++n) + ');', 500);
}


