using System;
using System.Configuration;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using System.Data.OleDb;
using System.Diagnostics;
using System.Web;
using System.Web.Services;
using System.IO;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Net;
using Geom;

namespace GenericImgCutout
{
    /// <summary>
    /// NonSDSSSurvey implementation details. Derived from Survey
    /// </summary>
    public class NonSDSSSurvey : Survey
    {
        public NonSDSSSurvey(string surveyName, string sConnect)
        {
            //
            // TODO: Add constructor logic here
            //
            this.surveyName = surveyName;
            this.sConnect = String.Copy(sConnect);

        }

        public override byte[] GetJpeg(
            double ra_,						// right ascension in J2000 degrees
            double dec_, 						// declination in J2000 degrees
            double scale_,						// arcsec/pixel (0.3961267 is native 1:1 for SDSS)
            Int32 width_,						// image width  (in pixels)
            Int32 height_,					// image height (in pixels)
            string opt_,						// drawing options
            string rid_,						// list of regionIDs
            string query_
            )
        {

            validateInput(ra_, dec_, scale_, height_, width_, opt_, rid_, query_);
            string qmsg = "ra=" + ra_.ToString("F5")
                + ", dec=" + dec_.ToString("F5") + "\n"
                + "scale = " + scale.ToString("F5") + "\n";


            /* Non SDSS Specific */
            zoom = 0;
            ppd = 3600.0 / scale;
            imageScale = ppd / FrameWCS.PixelsPerDegree;

            while (zoom < max_zoom & imageScale <= .5)
            {
                zoom++;											// go higher in the pyramid
                imageScale *= 2;								// change the scaling accordingly
            }
            zoomScale = (float)Math.Pow(2, zoom);				// set the scale according to the real zoom
            size = (float)((zoom > 3) ? 6 : 12 * imageScale);	// set symbol size based on zoom level


            qmsg += "imageScale = " + imageScale.ToString("F5") + "\n"
                + "zoomScale  = " + zoomScale.ToString("F5") + "\n";
            //--------------------------------------------------------------------------
            // set SQL search radii for fields and objects given in terms of ArcMinutes
            //--------------------------------------------------------------------------
            radius = 60.0 * 0.5 * Math.Sqrt(width * width + height * height) / ppd;
            fradius = FrameWCS.GetFrameHalfDiag () + radius;

            try
            {
                // Create a canvas object that holds information to map the WCS images to Screen
                canvas = new Canvas(width, height, imageScale, ppd, debug);
                connectToDataBase();

                // Non SDSS Specific Projection 
                canvas.InitializeProjection(ra, dec, ppd, "TAN");
                canvas.addDebugMessage(qmsg);

                ///<comment>
                /// This is not being used at all 
                ///</comment>
                // Get the viewPort 
                // viewPort = canvas.GetViewPort();

                //----------------------------------------
                if (drawFrames | drawField)
                    getFrames();

                if (drawField)
                    getFields();

                if (drawPhotoObjs | drawSpecObjs | drawTargetObjs)
                    getObjects();

                if (drawLabel) getLabel();
                if (drawGrid) canvas.drawCrosshair();
                
                //-----------------------------------------------
                // draw the debug messages before the inversion
                //-----------------------------------------------
                if (debug)
                {
                    canvas.drawAxis(ra, dec);
                    canvas.addDebugMessage(dbgMsg.ToString());
                    canvas.drawDebugMessage();
                }
                // Invert image if invert flag is present
                if (invertImage) canvas.Invert();
            }
            catch (Exception e)
            {
                canvas.displayMessage(e.Message);
            }
            finally { disconnectFromDataBase(); }

            // return the image to the calling routine (called from getJpeg ().
            return (canvas.getBuffer());

        }

        /// <summary>
        /// getFrames. Fetch the images and paint them onto the canvas.
        /// </summary>
        public override void getFrames()
        {
            FrameWCS currentFrame = null;		// coord of current frame
            Xform xform = null;					// the transform of current frame

            // Get the SQL to retrieve all the frames that are near to the
            // ref point using the fGetNearbyFrameEq function. This will also
            // return information about the frame i.e. (crval1, crval2, crpix etc)
            String frameSql = FrameWCS.GetFrameSQL(ra, dec, fradius, zoom, true);
            SqlCommand frameCommand = new SqlCommand(frameSql, SqlConn);

            if (debug && false) canvas.addDebugMessage("Frame Query: \n" + frameSql);

            try
            {
                xTable = new Hashtable();
                reader = frameCommand.ExecuteReader();

                while (reader.Read())
                {
                    //---------------------------------------------					
                    // get the astrometry parameters of this frame
                    //---------------------------------------------
                    currentFrame = new FrameWCS(reader, zoomScale, drawFrames);
                    string fieldId = currentFrame.fieldid;

                    //---------------------------------------------
                    // compute and save the canvas transformation
                    //---------------------------------------------
                    xform = new Xform(currentFrame, canvas.proj);
                    //xTable.Add(fieldId, xform);

                    if (debug) canvas.addDebugMessage(xform.dbgMsg);

                    if (drawFrames)
                    {
                        //---------------------------------
                        // draw the tile and discard bytes
                        //---------------------------------
                        canvas.drawFrame(xform, currentFrame.tile);
                        currentFrame.tile.Dispose();
                    }
                }
                if (reader != null) reader.Close();
            }
            catch
            {
                throw new Exception("Error in drawing Frames");
            }
        }

        /// <summary>
        /// getFields. Display the outlines of the Fields on the canvas.
        /// </summary>
        public override void getFields()
        {
            try
            {
                foreach (DictionaryEntry d in xTable)
                {
                    canvas.drawField((Xform)xTable[d.Key]);
                }
            }
            catch
            {
                throw new Exception("Error in drawing Field outlines");
            }
        }

        /// <summary>
        /// getObjects. Display a mark at the location of objects.
        /// </summary>
        public override void getObjects()
        {
            byte flag = 0;

            //for NDWFS
            StringBuilder sQ = new StringBuilder(" select ");
            sQ.Append("p.ra, p.dec, cast(2 as int) as flag ");
            sQ.AppendFormat("from dbo.fGetNearbyObjEq({0},{1},{2}) n, ", ra, dec, radius);
            sQ.Append("PhotoObjAll p where n.objid=p.objid and p.mag_iso<16");

            SqlCommand cmd = new SqlCommand(sQ.ToString(), SqlConn);
            try
            {
                double oRa, oDec;
                byte oFlag;

                reader = cmd.ExecuteReader();
                while (reader.Read())
                {
                    oRa = Convert.ToDouble(reader[0]);		// get ra
                    oDec = Convert.ToDouble(reader[1]);		// get dec
                    oFlag = Convert.ToByte(reader[2]);		// get flag												

                    if (drawSpecObjs && (oFlag & FrameWCS.sflag) > 0)
                        canvas.drawSpecObj(oRa, oDec, size);
                    if (drawPhotoObjs && (oFlag & FrameWCS.pflag) > 0)
                        canvas.drawPhotoObj(oRa, oDec, size);
                    if (drawTargetObjs && (oFlag & FrameWCS.tflag) > 0)
                        canvas.drawTargetObj(oRa, oDec, size);
                }
                if (reader != null) reader.Close();
            }
            catch (Exception e)
            {
                showException("getObjects() [Photo|Spec|Target]", sQ.ToString(), e);
            }
        }
    }
}
