  function month(name, numdays, abbr) 
	{
		this.name = name;
		this.numdays = numdays;
		this.abbr = abbr;
	}

	function Location(name, dlat, dlong, tz) 
	{
		this.name = name;
		this.latitude = dlat;
		this.longitude = dlong;
		this.timeZone = tz;
	}
  function SolarPosition(localTime, solarTime, azimuth, elevation)
  {
    this.localTime = localTime;
    this.solarTime = solarTime;
    this.azimuth = azimuth;
    this.elevation = elevation;
  }

  
function UpdateSunValues()
{
    // compute the sun position every 20 mins from sunrise to sunset
    // first clear the SunValues array
    SunValues.length = 0;
    var j = 0;
    for (i=0; i<24*3; i++)  {
      theSun.Update(i/3.0);      // time in hours
      if (theSun.elevation > -10) {
	      SunValues[j] = new SolarPosition(theSun.localTime, theSun.solarTime,
                                     theSun.azimuth, theSun.elevation);
	      j++;
      }
    }
    updated = true;
}

  function formatAngle(angle)
  {
    var str = "";
		var t = Math.round(angle * 100) / 100.0;
		str += t;
    return str;
  }
  function WriteSunValues()
  {
    var results = "";
    // heading
    results += "Local\tSolar\tAzimuth\tElevation\n";
    results += "Time\tTime\n";
    results += "-----\t-----\t-------\t---------\n";
    for (i=0; i<SunValues.length; i++) {
      results += formatTime(SunValues[i].localTime) + "\t" +
		 formatTime(SunValues[i].solarTime) + "\t" +
		 formatAngle(SunValues[i].azimuth) + "\t" +
		 formatAngle(SunValues[i].elevation) + "\n";  
    }
    document.OutputTable.Results.value = results;
  }
  function WriteSummary()
  {
    document.OutputTable.SolarTimeDiff.value = formatTimeDiff(theSun.timeDiff);
    document.OutputTable.SunriseTime.value = formatTime(theSun.sunRise);
    document.OutputTable.NoonTime.value = formatTime(theSun.noon);
    document.OutputTable.SunsetTime.value = formatTime(theSun.sunSet);
  }
  
// define months array for form
  var Months = new Array();	//	list of months and days (for non-leap year)
	var i = 0;
	Months[i++] = new month("January", 31, "Jan");
	Months[i++] = new month("February", 28, "Feb");
	Months[i++] = new month("March", 31, "Mar");
	Months[i++] = new month("April", 30, "Apr");
	Months[i++] = new month("May", 31, "May");
	Months[i++] = new month("June", 30, "Jun");
	Months[i++] = new month("July", 31, "Jul");
	Months[i++] = new month("August", 31, "Aug");
	Months[i++] = new month("September", 30, "Sep");
	Months[i++] = new month("October", 31, "Oct");
	Months[i++] = new month("November", 30, "Nov");
	Months[i++] = new month("December", 31, "Dec");
  
// define towns array for form
	var Towns = new Array();
	j = 0;
  Towns[j++] = new Location("Armidale",      -30.515, 151.663,	10);
  Towns[j++] = new Location("Coffs Harbour", -30.3,   153.117,	10);
  Towns[j++] = new Location("Glen Innes",    -29.717, 151.75,	10 );
  Towns[j++] = new Location("Inverell",      -29.767, 151.117,	10);
  Towns[j++] = new Location("Moree",	     -29.45,  149.5,	10);
  Towns[j++] = new Location("Sydney",	     -33.867, 151.2,	10);
  Towns[j++] = new Location("Tamworth",      -31.083, 150.917,	10);
  Towns[j++] = new Location("Uralla",	     -30.633, 151.5,	10);
  
// variables
  var updated = false;		      // values not calculated yet
  
  var SunValues = new Array();
  
// constants for Solar Chart
  var chartWidth = 623;
  var chartHeight = 390;
  var sunWidth = 25;   // size of sun image
  var sunHeight = 25;
  var xorigin = 60;    // left offset to origin of chart
  var yorigin = 309;	// top offset to origin of chart
  var xlength = 548;	// length of x axis
  var ylength = 277;	// length from origin to ymax
  var ylower = 340;   // top offset to bottom of y axis
  var az0 = -135;
  var az1 =  135;
  var el0 = 0;
  var el1 = 90;
  var animate = false;
  var isun = -1;
  
  function moveSun( lt, az, el)
  {
    //move sun image to position with specified azimuth and elevation
    if (az > 180)
      az -= 360;
    var left = (az - az0)/(az1-az0)*xlength + xorigin;
    var top =  yorigin - (el - el0)/(el1-el0)*ylength;
		// have to position centre correctly
    sunObj.left = left - sunWidth/2;
    sunObj.top = top - sunHeight/2;
    if (top + sunHeight/2 > ylower)
		    sunObj.visibility = hidden;
    else
		    sunObj.visibility = visible;
    // also update text boxes
    document.OutputTable.LocalTime.value = formatTime(lt);
    document.OutputTable.Azimuth.value = formatAngle(az);
    document.OutputTable.Elevation.value = formatAngle(el);
    
  }
  
  function resetAnimation()
  {
    isun = -1;
    animate = true;
  }
  function stopAnimation()
  {
    animate = false;
  }
  function startAnimation()
  {
    animate = true;
  }
  
  // timer function for animation
  function animateSun()
  {
    if (updated && animate) {
      isun++;
      if (isun == SunValues.length)
	isun = 0;
      var lt = SunValues[isun].localTime;
      var az = SunValues[isun].azimuth;
      var el = SunValues[isun].elevation;
      moveSun(lt, az, el);
    }
    // call self again in 200 ms
    setTimeout('animateSun()', 200);
  }
  
  function singleStep()
  {
    animate = false;
    if (updated) {
      isun++;
      if (isun == SunValues.length)
	isun = 0;
      var lt = SunValues[isun].localTime;
      var az = SunValues[isun].azimuth;
      var el = SunValues[isun].elevation;
      moveSun(lt, az, el);
    }
  }

    function Update()
    {
	    var month = parseInt(document.Calculator.SelectMonth.selectedIndex+1);
      var day = parseInt(document.Calculator.SelectDay.selectedIndex+1);
      var year = currentYear;
      if ( (year < 1901) || (year > 2099) )
	      year = 2001;
      var t = document.Calculator.SelectTown.selectedIndex;
      var latitude = Towns[t].latitude;	   // degrees (positive North)
      var longitude = Towns[t].longitude;	   // degrees (positive East)
      var timeZone = Towns[t].timeZone;	   // hours East of Greenwich
      // set the new postion and date for the Solar Calculator
      theSun.Initialise(latitude, longitude, timeZone, year, month, day);
      UpdateSunValues();       // update the array of sun positions for the day
      WriteSummary();	  // sunrise/sunset times
      WriteSunValues();

      resetAnimation();  // starts animation from beginning    
    }
    
    function setupTowns()
    {
      with (document) {
	      Calculator.SelectTown.options.length = Towns.length;
	      for (i = 0; i < Towns.length; i++) {
	        Calculator.SelectTown.options[i].text = Towns[i].name;
	        Calculator.SelectTown.options[i].value = i;
	        if(Towns[i].name == "Armidale") {
	          Calculator.SelectTown.options[i].selected = 1;
			    } 
        }
      }
		}    
    
    function setupMonths()
    {
      with (document) {
        Calculator.SelectMonth.options.length = Months.length;
        for (i = 0; i < Months.length; i++) {
	        Calculator.SelectMonth.options[i].text = Months[i].name;
	        Calculator.SelectMonth.options[i].name = Months[i].abbr;
	        Calculator.SelectMonth.options[i].value = i+1;	 // value is month number
	      } 
        Calculator.SelectMonth.options[currentMonth-1].selected = 1;
      }
      setupDays();
    }	    

    function setupDays()
    {
      with (document) {
        var m = Calculator.SelectMonth.selectedIndex;
        var numdays = Months[m].numdays;
        if ( (Months[m].abbr == 'Feb') && isLeapYear(currentYear) )
	        numdays++;
        Calculator.SelectDay.options.length = numdays;
        for (i = 0; i < numdays; i++) {
	        Calculator.SelectDay.options[i].text = i+1;	// text is day number
	        Calculator.SelectDay.options[i].value = i+1;	// value is day number
	      }
        if (initDate) 
	        Calculator.SelectDay.options[currentDay-1].selected = 1;
        }
    }
    
    function setup()
    {
      initDate = true;	    // initialise to current date
      now = new Date();
      currentYear = now.getYear();
      currentMonth = now.getMonth()+1;	 // number 1 - 12
      currentDay = now.getDate();
      setupTowns();
      setupMonths();
      initDate = false;
      
      // set up sun image for animation
      if(document.layers)
      {
	      sunObj = document.sunChartID.document.sun;
	      visible = "show";
	      hidden = "hide";
        document.sunChartID.document.sun.zIndex = document.sunChartID.zIndex+1;
        document.sunChartID.document.twilight.zIndex = document.sunChartID.zIndex+2;
      }
      else if(document.all)
      {
	      sunObj = sun.style;
	      visible = "visible";
	      hidden = "hidden";
      }
      else if (document.getElementById)
      {
	      sunObj = document.getElementById("sun").style;
	      visible = "show";
	      hidden = "hide";
      }
      sunObj.visibility = hidden;
      animate = false;
      updated = false;	   // sun values have not been calculated yet
      // have to call animation function, even though it won't do anything yet
      animateSun();
      
      Update();
    } 
  
