#!/usr/bin/env python2
# -*- coding: utf-8 -*-
"""
Created on Thu Jan 19 22:19:15 2017

@author: jaykalinani
"""

#Importing various required libraries
import wx

import numpy as np

from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.figure import Figure
from astroquery.sdss import SDSS
from astropy import coordinates as coords
from astropy.wcs import WCS


class MainWindow(wx.Frame):
    def __init__(self, parent, title):
        self.dirname=''
        
        # Creating the frame
        wx.Frame.__init__(self, parent, title=title, size=(900,650))
        
        # Creating the statusbar in the bottom
        self.CreateStatusBar()

        # Setting up the menu.
        filemenu= wx.Menu()
        menuAbout= filemenu.Append(wx.ID_ABOUT, "&About"," This program plots RA and DEC on Molleweide Projection")
        menuExit = filemenu.Append(wx.ID_EXIT,"&Exit"," Terminate the program")

        # Creating the menubar
        menuBar = wx.MenuBar()
        menuBar.Append(filemenu,"&File") # Adding the "filemenu" to the MenuBar
        self.SetMenuBar(menuBar)  # Adding the MenuBar to the Frame content.

        # Events
       
        self.Bind(wx.EVT_MENU, self.OnExit, menuExit)
        self.Bind(wx.EVT_MENU, self.OnAbout, menuAbout)
        
        # Adding sizers
        self.mainSizer = wx.BoxSizer(wx.VERTICAL)
        self.grid = wx.GridBagSizer(hgap=5, vgap=5)
        self.grid2 = wx.GridBagSizer(hgap=5, vgap=5)
        self.hSizer = wx.BoxSizer(wx.HORIZONTAL)
        
        # Adding a panel
        pnl1 = wx.Panel(self, -1)
       
        # Adding static text
        pnl1.quote = wx.StaticText(self, label="Enter the Right Ascension and Declination:")
        self.grid.Add(pnl1.quote, pos=(0,0))

       
        # Edit Control to input Right Ascension and Declination
        pnl1.lblname1 = wx.StaticText(self, label="Right Ascension (in deg):")
        self.grid.Add(pnl1.lblname1, pos=(2,0))
        self.ra_deg = wx.TextCtrl(self, value="0", size=(120,-1))
        self.grid.Add(self.ra_deg, pos=(2,1))
     
        pnl1.lblname2 = wx.StaticText(self, label="Declination (in deg):")
        self.grid.Add(pnl1.lblname2, pos=(3,0))
        self.dec_deg = wx.TextCtrl(self, value="0", size=(120,-1))
        self.grid.Add(self.dec_deg, pos=(3,1))
        
        pnl1.lblname3 = wx.StaticText(self, label="Origin (in deg):")
        self.grid.Add(pnl1.lblname3, pos=(4,0))
        self.org_deg = wx.TextCtrl(self, value="0", size=(120,-1))
        self.grid.Add(self.org_deg, pos=(4,1))
        
        #Creating figure for mollweide projection
        self.figure = Figure(figsize=(6.25, 3.7))
        self.axes = self.figure.add_subplot(111, projection='mollweide', axisbg ='LightCyan')
        self.canvas = FigureCanvas(self, -1, self.figure)
        
        # Creating figure to plot the found galaxy from SDSS
        self.figure2 = Figure(figsize=(6.25, 3.7))
        self.axes2 = self.figure2.add_subplot(111)
        self.axes2.clear()
        self.canvas2 = FigureCanvas(self, -1, self.figure2)
     
        # Defining the coordinates
        self.ra1 = float(self.ra_deg.GetValue())
        self.dec1 = float(self.dec_deg.GetValue())
        self.org1 = int(self.org_deg.GetValue())
        self.coord2 = np.array([(self.ra1,self.dec1)])

        # Plot Button
        self.button =wx.Button(self, label="Plot")
        self.Bind(wx.EVT_BUTTON, self.OnAdd, self.button)
        
        self.grid.Add(self.button, pos=(6,1))
        
        #Plotting the initial coordinates
        self.plot_mwd(self.coord2[:,0],self.coord2[:,1], self.org1, title ='Mollweide Projection')
        
        #Adding to the horizontal grid
        self.hSizer.Add(self.grid, 0, wx.ALL, 5)
        self.grid2.Add(self.canvas, pos = (0,0))
        self.grid2.Add(self.canvas2, pos = (2,0))
        self.hSizer.Add(self.grid2)
       
        # Adding to vertical sizer and setting the sizer in the frame
        self.mainSizer.Add(self.hSizer, 0, wx.ALL, 5)
        self.SetSizerAndFit(self.mainSizer)
        self.Show()

    def OnAbout(self,e):
        # Create a message dialog box
        dlg = wx.MessageDialog(self, "A simple program to plot the RA and Dec in Molleweide Projection ", "About Coordinate Plotter", wx.OK)
        # to show the dialogue
        dlg.ShowModal() 
        # Destroying it when finished
        dlg.Destroy() 

    def OnExit(self,e):
        
        # Close the frame
        self.Close(True)  

   
    # function to plot the RA and Dec on Mollweide projection
    def plot_mwd(self, RA, Dec, org, title='Mollweide projection'):
    
        x = np.remainder(RA+360-org,360) # shift RA values
        ind = x>180
        x[ind] -=360    
        x=-x    # reverse the scale: East to the left
        # create tick labels 
        tick_labels = np.array([150, 120, 90, 60, 30, 0, 330, 300, 270, 240, 210])
        tick_labels = np.remainder(tick_labels+360+org, 360)
        self.axes.clear()
        self.axes.scatter(np.radians(x),np.radians(Dec))  # Convert degrees to radians
        self.axes.set_xticklabels(tick_labels)     # Add the scale on the x axis
        self.axes.set_title(title)
        self.axes.title.set_fontsize(15)
        self.axes.set_xlabel("RA")
        self.axes.xaxis.label.set_fontsize(12)
        self.axes.set_ylabel("Dec")
        self.axes.yaxis.label.set_fontsize(12)
        self.axes.grid(True)
        self.canvas.draw()
        
    #Function to update and plot the user entered RA and Dec    
    def OnAdd(self, e):
        
        self.ra1 = float(self.ra_deg.GetValue())
        self.dec1= float(self.dec_deg.GetValue())
        self.coord2 = np.array([(self.ra1,self.dec1)])
        self.org1 = int(self.org_deg.GetValue())
        self.plot_mwd(self.coord2[:,0],self.coord2[:,1], self.org1, title ='Mollweide Projection')
        self.ra2 = self.ra_deg.GetValue()
        self.dec2 = self.dec_deg.GetValue()
        self.GalaxyFinder(self.ra2, self.dec2)
        
    def NotFound(self):
        
        dlg = wx.MessageDialog(self, "Object does not exist in SDSS database for given RA and DEC :( ","Object Not Found!",  wx.OK)
        dlg.ShowModal()
        dlg.Destroy()
        
    def Found(self):
        
        dlg = wx.MessageDialog(self, "Object Found! WOOOOHOOOOOO =) ","Object Found! Yippiee!",  wx.OK)
        dlg.ShowModal()
        dlg.Destroy()
      
      
    # To find and plot the galaxy from SDSS using the user-input ra and dec
    def GalaxyFinder(self, ra, dec):
        
        # getting the position coordinates
        pos = coords.SkyCoord(ra, dec, frame='icrs', unit='deg')
        # to query the SDSS about the position
        xid = SDSS.query_region(pos, spectro=True)
        
        if not xid:
            self.NotFound()
            
        else:
              #to get the image of the sky for the given ra and dec from SDSS 
            im = SDSS.get_images(matches=xid, band='r')
            hdulist = im[0]
            data = hdulist[0].data    
            
            #plot the image 
            self.axes2.clear()
            self.figure2.clear()
            
            wcs1 = WCS(hdulist[0].header)
            self.axes2 = self.figure2.add_axes([0.1, 0.1, 0.8, 0.8], projection = wcs1)
            #self.axes2.imshow(np.sqrt(data+1.), origin='lower',cmap='magma', vmax=1.05,vmin=0.95)
            self.axes2.imshow(np.sqrt(data+1.), origin='lower',cmap='magma', vmax=1.05,vmin=0.95)
            self.axes2.set_title('SDSS Sky View')
            self.axes2.title.set_fontsize(14)
            self.axes2.annotate('RA', xy=(1.05, 0), ha='left', va='top', xycoords='axes fraction', fontsize=12)
            self.axes2.set_ylabel("Dec")
            self.axes2.yaxis.label.set_fontsize(12)
            self.axes2.grid(True)
            
            self.canvas2.draw()
            self.Refresh()
            self.Found()
        