using System;
using System.IO;
using System.Collections;
using System.Configuration;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;

using Spherical;
using Spherical.IO;

namespace Galex
{
    class Program
    {
        static int Main(string[] args)
        {
            SqlConnection sqlconn = new SqlConnection
                ("Data Source=sdssdb001; Initial Catalog=galexcollab; User=test; Password=riuzg54; Timeout=60;");
            sqlconn.Open();

            Region skygrid;
            #region Load region of primary convexes for all skygrid points from embedded resource...

            /// load skygrid from embedded resource
            MemoryStream str = new MemoryStream(Properties.Resources.skygrid_v2);
            BinReader load = new BinReader(str);
            skygrid = load.ReadRegion();
            load.Close();

            #endregion

            Dictionary<long, Convex> galexfield = new Dictionary<long, Convex>(1000);
            Region galex = new Region(1000);
            Region circ = new Region(1000);
            float radius = 30; // arcmin
            #region Load actual fields from db and create their convexes...

            string sqlqry = @"
                select tilename, avaspra, avaspdec, photoextractid
                  from PhotoExtractMisN1000UnMarked
                ";
            try
            {
                SqlCommand sqlcmd = new SqlCommand(sqlqry, sqlconn);
                SqlDataReader sqlrdr = sqlcmd.ExecuteReader(CommandBehavior.SingleResult);
                char[] sep = new char[] { '_' };
                while (sqlrdr.Read())
                {
                    string tilename = sqlrdr.GetString(0);
                    double ra = sqlrdr.GetDouble(1);
                    double dec = sqlrdr.GetDouble(2);
                    long photoextractid = sqlrdr.GetInt64(3);
                    if (true)
                    {
                        string[] tok = tilename.Split(sep);
                        int grid = int.Parse(tok[1]);
                        Convex c = new Convex(skygrid.ConvexList[grid]);
                        Halfspace h = new Halfspace(ra,dec,radius);
                        circ.Add(new Convex(h));
                        c.Add(h);
                        c.Name = photoextractid.ToString();
                        c.Simplify(true, Const.Tolerance, Const.MaximumIteration);
                        galex.Add(c);
                        galexfield.Add(photoextractid, c);
                    }
                }
                sqlrdr.Close();
            }
            catch (SqlException sqlex)
            {
                Console.Error.WriteLine(sqlex);
                return 1;
            }
            #endregion

            Region galexmask = new Region();
            Region sdssmask = new Region();
            #region Load masks and intersect with primary areas and save...
            
            sqlqry = @"
                select photoextractid, area 
                  from Mask
                  where type>1  
                ";
            try
            {
                SqlCommand sqlcmd = new SqlCommand(sqlqry, sqlconn);
                SqlDataReader sqlrdr = sqlcmd.ExecuteReader(CommandBehavior.SingleResult);
                int counter = 0, counterPrimary = 0, counterInside = 0;
                while (sqlrdr.Read())
                {
                    counter++;
                    long photoextractid = sqlrdr.GetInt64(0);
                    if (galexfield.ContainsKey(photoextractid))
                    {
                        counterPrimary++;
                        string poly = sqlrdr.GetString(1);
                        Convex c = Convex.Parse(poly, false);
                        c.Intersect(galexfield[photoextractid]);
                        if (c.Simplify(true, Const.Tolerance, Const.MaximumIteration))
                        {
                            counterInside++;
                            galexmask.Union(c);
                        }
                    }
                }
                sqlrdr.Close();
                Console.Out.WriteLine("# of inside masks: {0} of {1} prim of {2} total ({3})", 
                    counterInside, counterPrimary, counter, galexmask.ConvexList.Count);
            }
            catch (SqlException sqlex)
            {
                Console.Error.WriteLine(sqlex);
                return 3;
            }

            sqlqry = @"
                select p.ra, p.dec
                  from PhotoPrimary p, PhotoExtractMisN1000Unmarked e
                  where p.photoextractid = e.photoextractid
                        and p.nuv_mag > 0.0
                        and p.nuv_mag < 16.5
                ";
            try
            {
                SqlCommand sqlcmd = new SqlCommand(sqlqry, sqlconn);
                SqlDataReader sqlrdr = sqlcmd.ExecuteReader(CommandBehavior.SingleResult);
                int counter = 0;
                while (sqlrdr.Read())
                {
                    counter++;
                    double ra = sqlrdr.GetDouble(0);
                    double dec = sqlrdr.GetDouble(1);
                    Halfspace h = new Halfspace(ra,dec,50.0/60.0);
                    Convex c = new Convex(h);
                    c.Simplify(false, Const.Tolerance, Const.MaximumIteration);
                    galexmask.Union(c);
                }
                sqlrdr.Close();
                Console.Out.WriteLine("# of bright-star masks: {0}", counter);
            }
            catch (SqlException sqlex)
            {
                Console.Error.WriteLine(sqlex);
                return 3;
            }

            sqlqry = @"
                select ra, dec, radius, area
                  from bestdr4..mask m, 
                	(select distinct s.run, s.rerun, s.camcol, s.field
                	  from PhotoPrimary p, PhotoExtractMisN1000Unmarked e, xSdssDr4 x, bestdr4..PhotoTag s
                	  where p.photoextractid = e.photoextractid and p.objid = x.objid and x.sdssobjid = s.objid
                		and p.nuv_mag < 16
                	) z
                  where m.run=z.run and m.rerun=z.rerun and m.camcol=z.camcol and m.field=z.field
                	and m.filter=2 and m.type < 4
                ";
            try
            {
                SqlCommand sqlcmd = new SqlCommand(sqlqry, sqlconn);
                SqlDataReader sqlrdr = sqlcmd.ExecuteReader(CommandBehavior.SingleResult);
                int counter = 0;
                while (sqlrdr.Read())
                {
                    counter++;
                    string poly = sqlrdr.GetString(3);
                    Convex c = Convex.Parse(poly, false);
                    c.Simplify(false, Const.Tolerance, Const.MaximumIteration);
                    sdssmask.Union(c);
                }
                sqlrdr.Close();
                Console.Out.WriteLine("# of SDSS masks: {0}", counter);
            }
            catch (SqlException sqlex)
            {
                Console.Error.WriteLine(sqlex);
                return 3;
            }

            BinWriter wri;
            wri = new BinWriter(@"C:\Temp\Ir11N1000UnmarkedPrimaryMasksF24.bin");
            wri.Write(galexmask);
            wri.Close();
            wri = new BinWriter(@"C:\Temp\Ir11N1000UnmarkedSdssMasks.bin");
            wri.Write(sdssmask);
            wri.Close();

            return 999; /// exit
                        
            #endregion

            SqlIO sqlio = new SqlIO(sqlconn);
            Region prim, spec;
            #region Load SDSS regions: PRIMARY for PhotoPrimary, SECTOR for SpecObj...

            try
            {

                List<long> idPrim = sqlio.QueryRegionId("select regionid from bestdr4..region where type='PRIMARY'");
                prim = new Region();
                foreach (long id in idPrim)
                {
                    Region r = sqlio.ReadRegion(id, "bestdr4..");
                    prim.Union(r);
                }
                prim.Simplify();
                Console.Out.WriteLine("# PRIMARY Area: {0}", prim.Area);

                List<long> idSpec = sqlio.QueryRegionId("select regionid from bestdr4..region where type='SECTOR'");
                spec = new Region();
                foreach (long id in idSpec)
                {
                    Region r = sqlio.ReadRegion(id, "bestdr4..");
                    r.Simplify();
                    spec.Union(r);
                }
                Console.Out.WriteLine("# SECTOR Area: {0}", spec.Area);
            }
            catch (SqlException sqlex)
            {
                Console.Error.WriteLine(sqlex);
                return 2;
            }

            #endregion

            sqlconn.Close();

#if false
            foreach (Convex c in galex.ConvexList)
            {
                Region r = new Region(prim);
                Region s = new Region(spec);
                r.SmartIntersect(c, Const.Tolerance, Const.MaximumIteration);
                s.SmartIntersect(c, Const.Tolerance, Const.MaximumIteration);

                Console.Out.Write("{0} {1}", c.Name, c.Area);
                Console.Out.Write(" {0:n}", r.Area.Value / c.Area.Value * 100);
                Console.Out.Write(" {0:n}", s.Area.Value / c.Area.Value * 100);
                Console.Out.WriteLine(" {0} {1}", r, s);
            }
#elif false
            Region isct = galex.SmartIntersect(spec, Const.Tolerance, Const.MaximumIteration);
            Console.Out.WriteLine("# Ir11MisN1000UnmarkedPrimary x Dr4Sector Area: {0}", isct.Area);
            isct.Sort(Convex.ComparisonAreaDescending);
            Console.Out.WriteLine("# Areas: {0} {1} ...", isct.ConvexList[0].Area, isct.ConvexList[1].Area);
            RandomPoint rnd = new RandomPoint();
            Console.Out.WriteLine("# Random Seed: {0}", rnd.Seed);
            for (int i = 0; i < 150000; )
            {
                Cartesian pt = rnd.Next(circ);
                if (isct.Covers(pt, 0))
                {
                    Console.Out.WriteLine("{0} {1} {2} {3}", pt.RA, pt.Dec, i, pt);
                    i++;
                }
            }

#endif
            return 0;
        }
    }
}
