using System;
using System.Collections.Generic;
using System.Text;
using Spherical;
using System.Data;
using System.Data.Sql;
using System.Data.SqlClient;

namespace Geom
{
    /// <summary>
    /// Class used to test drawing grid lines as constant lines of alpha and dec.
    /// </summary>
    class TestGridLines
    {
        // Parameters of the small circle
        private Cartesian viewportCenter, viewportCorner;
        private double centerDist;
        private double centerRa, centerDec;
        private SqlConnection connection;

        public static readonly int ra = 0;
        public static readonly int dec = 1;

        public TestGridLines(double ra, double dec)
        {
            this.centerRa = ra;
            this.centerDec = dec;
            viewportCenter = new Cartesian(ra, dec);

            setUpConnection();
        }

        /// <summary>
        /// Create the Halfspace corresponding to the viewport.
        /// The X,Y,Z are given by the center
        /// and the cosine is given by the angle made by the center vector and the 
        /// corner.
        /// </summary>
        /// <param name="cornerRa"></param>
        /// <param name="cornerDec"></param>
        public void createViewportHalfspace (double cornerRa, double cornerDec)
        {
            viewportCorner = new Cartesian(cornerRa, cornerDec);

            // fourth parameter for halfspace i.e. cosine = dot product
            centerDist = viewportCenter.Dot(viewportCorner);
        }

        public void setUpConnection()
        {
            string connString = "Initial Catalog=BESTDR4;Data Source=sdssdb001;User ID=test;Password=riuzg54;timeout=120";
            try
            {
                connection = new SqlConnection(connString);
            }
            catch (SqlException ex)
            {
                Console.Out.WriteLine (ex);
            }
        }

        public void getGridArc (string query, out double ra1, out double dec1, out double ra2, out double dec2, out bool drawable)
        {
            ra1 = 0;
            ra2 = 0;
            dec1 = 0;
            dec2 = 0;
            drawable = false;
            try
            {
                SqlCommand cmd = new SqlCommand(query, connection);
                SqlDataReader reader;
                connection.Open();
                reader = cmd.ExecuteReader();

                if (reader.HasRows)
                {
                    reader.Read();
                    ra1 = reader.GetDouble(6);
                    dec1 = reader.GetDouble(7);
                    ra2 = reader.GetDouble(8);
                    dec2 = reader.GetDouble(9);
                    drawable = true;
                }

                connection.Close();
            }
            catch (SqlException ex)
            {
                Console.Out.WriteLine(ex);
            }
        }

        public HTMRegion LineRegion(double ra1, double dec1, double ra2, double dec2, double angularWidth, bool positiveNormal)
        {
            double dRA1 = angularWidth / (2.0 * Math.Cos(dec1 * V3.D2R));
            double dRA2 = angularWidth / (2.0 * Math.Cos(dec2 * V3.D2R));

            double[] p1 = new double[2];
            double[] p2 = new double[2];
            double[] p3 = new double[2];
            double[] p4 = new double[2];

            p1[ra] = ra1 + dRA1;
            p1[dec] = dec1;
            p2[ra] = ra1 - dRA1;
            p2[dec] = dec1;
            p3[ra] = ra2 - dRA2;
            p3[dec] = dec2;
            p4[ra] = ra2 + dRA2;
            p4[dec] = dec2;

            Console.Error.WriteLine("endpoints (" + ra1 + ", " + dec1 + "), (" + ra2 + ", " + dec2 + ")");
            Console.Error.WriteLine("dRA1 = " + dRA1 + " dRA2 = " + dRA2);
            Console.Error.WriteLine("p1 = (" + p1[ra] + ", " + p1[dec] + ")");
            Console.Error.WriteLine("p2 = (" + p2[ra] + ", " + p2[dec] + ")");
            Console.Error.WriteLine("p3 = (" + p3[ra] + ", " + p3[dec] + ")");
            Console.Error.WriteLine("p4 = (" + p4[ra] + ", " + p4[dec] + ")");
            Console.Error.Flush();
            double[] n = V3.Normalize(V3.Wedge(V3.Normal(p1[ra], p1[dec]), V3.Normal(p2[ra], p2[dec])));
            HTMArc arc1 = new HTMArc(0, 0, 1, p1[ra], p1[dec], p2[ra], p2[dec], n[0], n[1], n[2], 0, 0);
            if (positiveNormal)
            {
                n = V3.Normalize(V3.Wedge(V3.Normal(p2[ra], p2[dec]), V3.Normal(p3[ra], p3[dec])));
            }
            else
            {
                n = V3.Normalize(V3.Wedge(V3.Normal(p3[ra], p3[dec]), V3.Normal(p2[ra], p2[dec])));
            }
            HTMArc arc2 = new HTMArc(0, 0, 1, p2[ra], p2[dec], p3[ra], p3[dec], n[0], n[1], n[2], 0, 0);
            n = V3.Normalize(V3.Wedge(V3.Normal(p3[ra], p3[dec]), V3.Normal(p4[ra], p4[dec])));
            HTMArc arc3 = new HTMArc(0, 0, 1, p3[ra], p3[dec], p4[ra], p4[dec], n[0], n[1], n[2], 0, 0);
            if (positiveNormal)
            {
                n = V3.Normalize(V3.Wedge(V3.Normal(p4[ra], p4[dec]), V3.Normal(p1[ra], p1[dec])));
            }
            else
            {
                n = V3.Normalize(V3.Wedge(V3.Normal(p1[ra], p1[dec]), V3.Normal(p4[ra], p4[dec])));
            }
            HTMArc arc4 = new HTMArc(0, 0, 1, p4[ra], p4[dec], p1[ra], p1[dec], n[0], n[1], n[2], 0, 0);
            HTMRegion region = new HTMRegion(0, 0, "PRIMARY");
            region.arc = new HTMArc[] { arc1, arc2, arc3, arc4 };

            return region;
        }

        public double CenterRa
        {
            get { return centerRa; }
            set { centerRa = value; }
        }

        public double CenterDec
        {
            get { return centerDec; }
            set { centerDec = value; }
        }

        public double CenterDist
        {
            get { return centerDist; }
            set { centerDist = value; }
        }

        public double CenterX
        {
            get { return viewportCenter.X; }
            set { viewportCenter.X = value; }
        }

        public double CenterY
        {
            get { return viewportCenter.Y; }
            set { viewportCenter.Y = value; }
        }

        public double CenterZ
        {
            get { return viewportCenter.Z; }
            set { viewportCenter.Z = value; }
        }
    }
}
