import tkinter
import customtkinter
import math

from matplotlib.backends.backend_tkagg import (FigureCanvasTkAgg, NavigationToolbar2Tk)
# Implement the default Matplotlib key bindings.
from matplotlib.backend_bases import key_press_handler
from matplotlib.figure import Figure

import numpy as np

class GraphFrame(customtkinter.CTkFrame):

    SIGMA = 5.67051e-5                                                         # Stefan-Boltzmann Constant
    PI    = math.pi                                                            # Pi
    M_SUN = 1.989e33                                                           # Solar mass (g)
    L_SUN = 3.826e33                                                           # Solar luminosity (ergs/s)
    R_SUN = 6.9599e10                                                          # Solar radius (cm)
    YEAR  = 3.15570e7                                                          # AU year (s)

    filenames = ['dummymain.lst']
    colours = ['r', 'g', 'b', 'c', 'm']
    lines = ['solid', 'dotted', 'dashed', 'dashdot']
    
    def __init__(self, *args, header_name = "GraphFrame", graph="G0", **kwargs):
        super().__init__(*args, **kwargs)

        self.header = customtkinter.CTkLabel(self, text=header_name)
        self.header.grid(row=0, column=0, padx=5, pady=5)
        
        self.sc = MplCanvas(self, width=5, height=4, dpi=100)

        sa_sun = 4 * self.PI * math.pow(self.R_SUN, 2)                         # Solar surface area
        t_sun  = self.L_SUN / (sa_sun * self.SIGMA)                            # Solar surface temperature
        
        for index, filename in enumerate(self.filenames):
            stellarData = self.readData(filename)
            colour = self.colours[index % 5]
            line = self.lines[index // 4]

###########################################

            # MAKE CM GRAPH
            #CM_Graph(stellarData[:, 4],stellarData[:, 3], filename, colour, line)
            
            l_star = stellarData[:, 4] / self.L_SUN                                                                            # Calculate the ratio between the star's luminosity and our Sun's
            r_star = np.power(stellarData[:, 3] / self.R_SUN, 2)                                                                # Calculate the ratio between the star's radius and our Sun's
    
            t_star = np.power((t_sun * l_star) / r_star, 0.25)                                                                            # Calculates the temperature of the star

            self.sc.axs.loglog(t_star[:], l_star[:], color=colour, linestyle=line, label=filename)
    
            self.sc.axs.set_title(r'Temperature Magnitude (TM) Diagram')
            self.sc.axs.set_xlabel(r'Surface Temperature (Kelvin) - ${(\frac{t_{\odot} \times L_{\star}}{R_{\odot}})}^\frac{1}{4}$')
            self.sc.axs.set_ylabel(r'Luminosity (Solar Units) - $\frac{L_{\star}}{L_{\odot}}$')
            # END OF CM GRAPH
                        
        self.sc.axs.invert_xaxis()
        self.sc.axs.legend()
        
        self.sc.get_tk_widget().grid(row = 0, column = 0)


    def convert(self, oldValue):
        if oldValue.find('D') != -1:
            newValue = float(oldValue.replace('D', 'e'))
        else:
            if oldValue.find('+') != -1:
                mantissa = float(oldValue[0: oldValue.find('+')])
                exponent = int(oldValue[oldValue.find('+'):])
            else:
                mantissa = float(oldValue[0: oldValue.find('-')])
                exponent = int(oldValue[oldValue.find('-'):])

            newValue = mantissa * (math.pow(10, exponent))
        return newValue

    def readData(self, datafile):
        data = np.empty((0, 8), float)
        
        # Create an empty Numpy 2D array of 0 rows and 8 columns; all of the data type float
        keyword = "hydro"
        print(f"Starting to read and analyse file {datafile}")
        file = open(datafile)
    
        for attempts in range(4):
            try:
                for line in file:
                    if keyword.casefold() in line.casefold():
                        time      = self.convert(line[21:35])                  # Timestep
                        delta_t      = self.convert(line[36:50])                  # Change in timestep
                        mass      = self.convert(line[51:65])                  # Mass of star (excluding envelope)
                        radius    = self.convert(line[66:80])                  # Radius of star (excluding envelope)
                        lum_core  = self.convert(line[81:95])                  # Luminosity of star (excluding envelope)
                        lum_tot   = self.convert(line[96:110])                 # Total luminosity (including enveloping cloud)
                        flux      = self.convert(line[111:125])                # Mass flux
                        ratio     = float(line[125:137])                       # Ratio of star mass against mass of the Sun
                
                        # Store the data into the Numpy array 'data'
                        data = np.append(data, np.array([[time, delta_t, mass, radius, lum_core, lum_tot, flux, ratio]]), axis = 0)
                break
            except ValueError as error:
                if attempts < 3:
                    file.close()
                    file = open(datafile, encoding="utf-16")
                else:
                    print("Error in file")
                    print(error)    
        file.close()                                                           # Close data file
        return data


class MplCanvas(FigureCanvasTkAgg):
    
    def __init__(self, parent=None, width=5, height=4, dpi=100):
        fig = Figure(figsize=(width, height), dpi=dpi)
        self.axs = fig.add_subplot(111)                                                                                    # Create a subplot as a single plot
        super(MplCanvas, self).__init__(fig)
