using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

using Spherical;

namespace Galex
{
    public class SkyGrid
    {
        public List<Cartesian> pointList;

        public SkyGrid()
        {
            pointList = new List<Cartesian>(50000);
        }

        public Region Load(string gridFile, string neighborFile)
        {
            char[] sep = new char[] { ' ', ',', '\t' };
            StreamReader rdr;
            string line;

            // read grid points
            pointList = new List<Cartesian>(50000);
            rdr = new StreamReader(gridFile);
            double ra, dec;
            int counter = 0;
            line = null;
            while ((line = rdr.ReadLine()) != null)
            {
                string[] tok = line.Trim().Split(sep);
                if (counter != int.Parse(tok[0]))
                    throw new ArgumentException("SkyGrid.Load(): id is not in order?");
                ra = double.Parse(tok[1]);
                dec = double.Parse(tok[2]);
                this.pointList.Add(new Cartesian(ra, dec));
                counter++;
            }
            rdr.Close();

            // read neighbors
            int[][] neighbors = new int[pointList.Count][];
            rdr = new StreamReader(neighborFile);
            line = null;
            while ((line = rdr.ReadLine()) != null)
            {
                string[] tok = line.Trim().Split(sep);
                int n = tok.Length;
                if (n > 7) throw new ArgumentException
                        ("SkyGrid.Load(): too many neighbors, should not happen!");
                int id = int.Parse(tok[0]);
                neighbors[id] = new int[n - 1];
                for (int i = 1; i < n; i++)
                    neighbors[id][i - 1] = int.Parse(tok[i]);
            }
            rdr.Close();

            // build convexes of primary fields
            Region region = new Region(pointList.Count);
            for (int i = 0; i < this.pointList.Count; i++)
            {
                Convex c = new Convex(null, neighbors[i].Length);
                Cartesian o = this.pointList[i];
                for (int k = 0; k < neighbors[i].Length; k++)
                {
                    Cartesian n = this.pointList[neighbors[i][k]];
                    Halfspace h = new Halfspace 
                        (o.X - n.X, o.Y - n.Y, o.Z - n.Z, true, 0);
                    c.Add(h);
                }
                region.Add(c);
            }
            return region;
        }
    }
}

#region Main() that saved the neighbors originally
/* 
 * this function saved the neighbor's table into csv that is read in SkyGrid
 * 
		[STAThread]
		static int Main(string[] args)
		{
			Cartesian p = new Cartesian();
			HalfSpace h = new HalfSpace();
			Console.WriteLine(h);
			return 0;

			Cartesian[] grid;
			int[] fieldId;

			// read Cartesianings
			LoadGrid (@"H:\work\galex\galex-skygrid-v2.csv", out grid, out fieldId);
			// write neighbors
			StreamWriter csv = new StreamWriter
				(@"H:\work\galex\galex-skygrid-v2-neighbors.csv.tmp", 
				false, System.Text.Encoding.ASCII);

			// save them in dictionary
			PrimaryFieldDict field = new PrimaryFieldDict();
			double arcmin = 36;

			// find neightbors (inside 2x radius but not self)
			for (int i=0; i<fieldId.Length; i++) // fieldId.Length
			{
				int id = fieldId[i];
				Cartesian center = grid[i];
				ArrayList index = new ArrayList(6);
				// find neighbors inside 2x the radius
				HalfSpace range = new HalfSpace 
					(center, Math.Cos(2*arcmin*Util.Arcmin2Radian));
				for (int j=0; j<fieldId.Length; j++)
				{
					if (j==i) continue;
					if (range.Covers(grid[j])) 
						index.Add(j);
				}
				Cartesian[] neigh = new Cartesian[index.Count];
				for (int k=0; k<neigh.Length; k++) neigh[k] = grid[(int)index[k]];
				
				// add to dict
				field.Add(id,new PrimaryField(id,center,arcmin,neigh));

				// write CSV file with id and neighbors
				csv.Write(i); 
				for (int k=0; k<neigh.Length; k++) 
					csv.Write(",{0}",(int)index[k]);
				csv.WriteLine();

				// progress report to stdout
				if (i%500==0) Console.Out.WriteLine(" {0}", i);

			}
			csv.Close();

			return 0;
		}
*/
#endregion