///Current version
///ID:          $Id: ImgCutout.cs,v 1.1.1.1 2006/11/14 02:56:48 gupchup Exp $
///Revision:    $Revision: 1.1.1.1 $
///Date:        $Date: 2006/11/14 02:56:48 $ 
///
///
/// Revision history:
///*	2002-04-01 Alex+Jim: First design
///*	2002-06-01 Alex+Jim: Went from "zoom" to pixels per degree, rotated image 
///*						 so north is up, added tick marks and more detailed label,
///*						 added support for inverted images, performance improvements 
///*						 and went to stored procedure.
///*	2002-07-01 Alex+Jim: Cleaned up code and added more documentation,
///*  						 deallocated SQL connections (self garbage collection).
///* 						 Replaced exceptions with returned images containing diagnostic 
///*						 message. Fixed a bug in the tick calculation, revised the text
///*						 in the image label.
///*	2003-02-01 Alex+Jim: Change tile for img in queries in order to query for Frames 
///*						 and Mosaic. Patch to account for new zoom clipping 
///*						 (xZoomClippingOffset, yZoomClippingOffset).
///*	2003-02-14 Tamas:	 Clean-up and handling string option opt.
///*	2003-02-20 Maria: 	 Clean-up code: variables renamed, added Bounding Box
///*	2003-03-06 Maria:	 New functionalities AND splitting and clean-up code.
///*						 Added Target, BoundingBox, Fields, Mask, Plates, modified ruler.
///*	2003-07-21 Maria:	 For PersonalSkyserver Dr1: moved to center on 195,2.5,
///*						 converted from fGetJpegObjects to fGetObjectsEq.
///*	2004-03-01 Alex:	 Added various Projections
///*	2004-03-10 Alex:	 Added Region display, also option to turn the images off.
///*	2004-11-08 Alex:	 Added image handling via WCS
///
///*    2005-10-08 Jayant :  i) Added another type to projections which define SDSS Projection 
///							 Symantics and to keep it consistent with the Projection Interface definitions
///                          ii) Changed the interface in ImgCutOut code to maintain consistency between 
///                          SDSS Surveys and Non-SDSS (WCS, NDWFS implementation) function calls.
///*    2006-1-24 Jayant :   Cleaned the Code and separated SDSS Specific and non-SDSS specific codes
///*                         by creating a new class called Survey, which contained all the common features
///*                         and then 2 derived classes viz SDSSSurvey and NonSDSSSurvey based which define
///*                         the functionality of the different survey types.
///   

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>
    /// Imgcut (Generic) returns a JPEG image from the SDSS image archive
    /// or any image database archive that maintains fits in WCS format.
    /// The image can be up to 2000x2000 pixels mosaiced from the base data.
    /// The image can be zoomed from 100 pixels per degree to 1,000,000 
    /// pixels per degree. It is rotated so that north is up.
    /// The image optionally contains PhotoObj, SpecObj and Target icons 
    /// and a label and grid. The image may be inverted.
    /// </summary>
    /// 
    [WebService(Namespace = "http://localhost/",
         Description = "This is an <b>XML Web Service</b> interface to fetch "
         + "<b>JPEG</b> image cutouts from the <bNDWFS</b> image archive."
         + "<br>Send comments to <b>Jayant Gupchup</b> -- gupchup@pha.jhu.edu")]

    public class ImgCutout : System.Web.Services.WebService
    {
        //-------------------------------------
        // Survey Properties
        // ------------------------------------
        private string sDataRelease = null; //DR1, DR2 ...
        private string surveyName = "";
        private bool sdssSurveyType = false;

        private string sConnect = null;
        Canvas canvas = null;

        /// <summary>
        /// Revision from CVS
        /// </summary>
        public static string Revision
        {
            get
            {
                return "$Revision: 1.1.1.1 $";
            }
        }

        [WebMethod(Description = "Return CVS revision numbers")]
        public string[] Revisions()
        {
            string[] revs = {
								"ImgCutout:WebServices "+ImgCutout.Revision,
			};
            return revs;
        }

        /// <summary>
        /// The constructor is used to determine if the survey is a SDSS survey
        /// or a non-SDSS survey. If it is an SDSS survey, the sdssSurveyType boolean
        /// variable is set to true and from here on the branching occurs based
        /// on whether it is a SDSS survey or not because implementation details
        /// are different for SDSS surveys and non-SDSS surveys.
        /// </summary>
        public ImgCutout()
        {
            //CODEGEN: This call is required by the ASP.NET Web Services Designer
            InitializeComponent();
            try { sConnect = ConfigurationSettings.AppSettings["SkyServer"]; }
            catch { ;}
            if (sConnect == null)
                throw new ApplicationException("Database not found in config file!");

            // Get the name of the survey
            // The idea behind this is to isolate the SDSS specific actions
            // and the non-SDSS specific actions
            try
            {
                // Get the value corresponding to SkyServer
                string appSettingsKey = ConfigurationSettings.AppSettings["SkyServer"];

                // Split the Value around the first ';' so that you get initial Value
                string[] split1 = appSettingsKey.Split(';');

                // Split the Initial Catalog around '='
                string[] split2 = split1[0].Split('=');

                // SurveyName is the second part of the split
                surveyName = split2[1];

                // Check if this is an SDSS Survey and set the flag accordingly
                sdssSurveyType = SdssConstants.isSDSSSurvey(surveyName);
            }
            catch (Exception e)
            {
                canvas.displayMessage(e.Message);
            }

            // If sdss survey then set the clipping properties and the other properties.
            if (sdssSurveyType)
            {
                SdssConstants.setRelease(ConfigurationSettings.AppSettings["DataRelease"].ToUpper());
                sDataRelease = SdssConstants.sDataRelease;
                if (SdssConstants.eDataRelease == SdssConstants.Release.DR)
                    sDataRelease = null;

                if (sConnect == null || sDataRelease == null)
                    throw new System.Exception("SkyServer or DataRelease keywords not found or invalid. \n" +
                        "Please check AppSettings in the Web.config file!");
            }
            // Set the FrameHeight, FrameWidth and PixelsPerDegree properties
            else
            {
                // Set Scale parameters.
                FrameWCS.FrameWidth = float.Parse(ConfigurationSettings.AppSettings["FrameWidth"].ToString());
                FrameWCS.FrameHeight = float.Parse(ConfigurationSettings.AppSettings["FrameHeight"].ToString());
                FrameWCS.PixelsPerDegree = float.Parse(ConfigurationSettings.AppSettings["PixelsPerDegree"].ToString());
                FrameWCS.PixelsPerArcMin = FrameWCS.PixelsPerDegree / 60.0;

                if (FrameWCS.FrameWidth == 0.0F || FrameWCS.FrameHeight == 0.0F || FrameWCS.PixelsPerDegree == 0.0F)
                    throw new System.Exception("\n FrameWidth, FrameHeight or PixelsPerDegree keywords not found or invalid. " +
                        "Please check AppSettings in the web.config file !");

            }


        }

        #region Component Designer generated code

        //Required by the Web Services Designer 
        private IContainer components = null;

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
        }

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        protected override void Dispose(bool disposing)
        {
            if (disposing && components != null)
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #endregion

        /// <summary>
        /// GetJpeg retuns a Jpeg of the image around a point at the specified zoom.
        ///		optionally draws circles/squares/crosses around photo/spectro/target objects
        ///		optionally draws a grid on the output 
        ///		optionally labels the output.
        ///		optionally inverts the image.
        ///		
        ///		It throws an authorization exception if it cannot connect to the database.
        /// </summary>
        /// 
        /// <param name="ra"> The image center point right ascencion in J2000 degrees. Should be double in [-90..90]</param>
        /// <param name="dec"> The image center point declination in J2000 degrees. Should be double in [0...360]</param>
        /// <param name="scale"> Arcseconds per pixel. Limited to the range 60..240,000.
        /// The native number for SDSS is 0.396126761"/pixel.
        ///          </param>
        /// <param name="height"> The image height in pixels. Should be int in [16..2048] </param>
        /// <param name="width"> The image width in pixels. Should be int in [16..2048], int</param>
        /// <param name="opt"> String coding over drawing requests: 
        ///			'P': draws Photo Objects
        ///			'S': draws Spectro Objects
        ///			'T': draws Target Objects
        ///			'G': draws a Grid
        ///			'L': draws a Label
        ///			'B': draws BoundingBox
        ///			'O': draws Outline
        ///			'M': draws Mask 
        ///			'Q': draws Plate 
        ///			'I': inverts Image </param>
        /// <returns> byte[] JPEG image.</returns>
        /// <example> 
        ///		ws.GetJpeg(ra, dec, scale, height, width, opt)
        /// </example>
        /// <remarks>
        ///		1) Originally the functionality was implemented in this method but because we had to deal with 
        ///		SDSS surveys and Non-SDSS surveys, another class called Survey.cs was created which
        ///		had a base common class and then had 2 derived classes called SDSS Survey and Non-SDSS survey
        /// </remarks>

        [WebMethod(BufferResponse = false,
             Description = "Returns the bytes of the Jpeg image for a given pointing"
             + "<br><b>Input 2:</b> RA in degrees (double)"
             + "<br><b>Input 3:</b> Dec in degrees (double)"
             + "<br><b>Input 4:</b> Scale, in arcsec/pixel (double)"
             + "<br><b>Input 5:</b> Width in pixels (int)"
             + "<br><b>Input 6:</b> Height in pixels (int)"
             + "<br><b>Input 7:</b> Drawing options (string)"
             + "<br><b>Input 8:</b> list of regionids (string)"
             + "<br><b>Output:</b> Image (byte[])")]

        public 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_
            )
        {
            // If the boolean is sdssSurveyType then call the SDSS specific code tree
            // else call the NonSDSS specific code tree.
            if (sdssSurveyType)
            {
                SDSSSurvey sdssSurvey = new SDSSSurvey(surveyName, sConnect);
                return sdssSurvey.GetJpeg(ra_, dec_, scale_, width_, height_, opt_, rid_, query_);
            }
            else
            {
                NonSDSSSurvey nonSdssSurvey = new NonSDSSSurvey(surveyName, sConnect);
                return nonSdssSurvey.GetJpeg(ra_, dec_, scale_, width_, height_, opt_, rid_, query_);
            }
        }

    }
}

/// <Remark>
/// The DimeJPeg has been deprecated but the code has been kept incase support wants to be 
///		renewed. It could be removed as the current version doesnt use it
/// </Remark>
/// 
/*
/// <summary>
/// This is a DIME wrapper, see method GetJpeg() above
/// </summary>
[WebMethod (Description="Returns the Jpeg image for a given pointing in a SOAP attachment (DIME)"
+ "<br><b>Input 1:</b> RA in degrees J2000 (double)"
+ "<br><b>Input 2:</b> Dec in degrees J2000 (double)"
+ "<br><b>Input 3:</b> Scale, in arcsec/pixel (double)"
+ "<br><b>Input 4:</b> Width in pixels (int)"
+ "<br><b>Input 5:</b> Height in pixels (int)"
+ "<br><b>Input 6:</b> Drawing options (string)"
+ "<br><b>Output:</b> Jpeg image in attachment")]


public void DimeJpeg(
    double ra_,						// right ascension in J2000 degrees
    double dec_, 					// declination in J2000 degrees
    double scale_,					// arcsec/pixel 
    int width_,						// image width  (in pixels)
    int height_,					// image height (in pixels)
    string opt_,					// drawing options
    string rid_
    )
{
    this.GetJpeg(ra_, dec_, scale_, width_, height_, opt_, rid_);

    // return image in attachment
    MemoryStream stream = new MemoryStream();
    this.canvas.image.Save(stream,ImageFormat.Jpeg);

    DimeAttachment attchmnt = new DimeAttachment
        ("ImgCutOut", "image/jpeg", TypeFormatEnum.MediaType, stream);
    HttpSoapContext.ResponseContext.Attachments.Add(attchmnt);
}
*/



/* Revision History

        $Log: ImgCutout.cs,v $
        Revision 1.1.1.1  2006/11/14 02:56:48  gupchup
        no message

        Revision 1.1.1.1  2006/04/25 16:07:22  gupchup
        Code base that merges original imgcutout code and WCS frame format imgcutout code
		
		Revision 1.20 2006/01/24 Jayant
		Added new class type to projections
		Separated SDSS and non-SDSS (WCS) specific code trees
		created new class Survey.cs which does the above.
		Added marias mark objects by query		
		fixed bugs in the WCS version from Alex to show WCS frames.

		Revision 1.19 2003/07/22  Gray
		 recentered on 195., 2.5 for DR1 Personal Skyserver 
		 converted from fGetJpegObject() to fGetObjectsEq()

        Revision 1.18  2003/04/10 21:54:32  szalay
         projection interface added

        Revision 1.17  2003/04/08 17:12:00  nieto
        Trying to include projection.cs class in project

        Revision 1.16  2003/03/25 23:18:33  nieto
        testing draw fields with their own coord

        Revision 1.15  2003/03/19 18:49:55  nieto
        more clean up

        Revision 1.14  2003/03/19 01:02:45  nieto
        split up of classes

        Revision 1.13  2003/03/18 23:13:13  nieto
        get_XY() has been changed for get_XYF(). Radius for searching frames and fields is now the same.

        Revision 1.12  2003/03/18 22:09:05  budavari
        New DIME interface called DimeJpeg() that returns the image in a SOAP attachment. Also added descriptions that show up in the WSDL

        Revision 1.11  2003/03/18 18:39:46  nieto
        added a property to retrieve the bitmap

        Revision 1.10  2003/03/18 16:39:10  nieto
        New Alex Modifications

        Revision 1.9  2003/03/18 00:20:12  nieto
        New Version of ImgCutout into development directory

        Revision 1.8  2003/03/17 21:41:27  nieto
        No display ImageFrame set antialiasing for bounding box

        Revision 1.7  2003/03/14 15:30:02  nieto
        Antialiasing for fields & first coord frezing

        Revision 1.6  2003/03/13 02:34:58  nieto
        Modify Mask query to include considerated to be important Masks

        Revision 1.5  2003/03/13 01:30:07  nieto
        Outlines and Bounding Boxes Working

        Revision 1.4  2003/03/11 22:18:04  nieto
        New Implementation of Plates

        Revision 1.3  2003/03/08 01:10:36  nieto
        Floats for Plates & Outlines

        Revision 1.2  2003/03/07 15:38:27  nieto
        Adding Outline

*/




