from .Generaldistribution import Distribution
import numpy as np
import matplotlib.pyplot as plt
import math

class Gaussian(Distribution):

    """ Gaussian distribution class for calculating and 
	visualizing a Gaussian distribution.
	
	Attributes:
		mean (float) representing the mean value of the distribution
		stdev (float) representing the standard deviation of the distribution
		data_list (list of floats) a list of floats extracted from the data file
			
	"""

    def __init__(self, mu=0, sigma =1):
        Distribution.__init__(self, mu, sigma)

    def calculate_mean(self):

        """Function to calculate the mean of the data set.
		
		Args: 
			None
		
		Returns: 
			float: mean of the data set
	
		"""

        mean = sum(self.data) / len(self.data)
        self.mean = mean
        return mean


    def calculate_stdev(self, sample = True):

        """Function to calculate the standard deviation of the data set.
		
		Args: 
			sample (bool): whether the data represents a sample or population
		
		Returns: 
			float: standard deviation of the data set
	
		"""

        arr = np.array(self.data)
        if sample:
            stdev = np.std(arr, ddof=1)
            self.std = stdev
            
        else:
            stdev = np.std(arr, ddof=0)
            self.std = stdev
        return stdev


    def __add__(self, other):

        """Function to add together two Gaussian distributions
		
		Args:
			other (Gaussian): Gaussian instance
			
		Returns:
			Gaussian: Gaussian distribution
			
		"""

        result = Gaussian()
        result.mean = self.mean + other.mean 
        result.std = math.sqrt(self.std ** 2 + other.std ** 2)
        return result


    def __repr__(self):

        """Function to output the characteristics of the Gaussian instance
		
		Args:
			None
		
		Returns:
			string: characteristics of the Gaussian
		
		"""

        return f"mean: {self.mean}, standard deviation: {self.std}"


    def plot_histogram(self):

        """Function to output a histogram of the instance variable data using 
		matplotlib pyplot library.
		
		Args:
			None
			
		Returns:
			None
		"""

        plt.hist(self.data)
        plt.title('Histogram of Data')
        plt.xlabel('data')
        plt.ylabel('count')
        plt.show()
    

    def pdf(self, x: float):

        """Probability density function calculator for the gaussian distribution.
		
		Args:
			x (float): point for calculating the probability density function
			
		
		Returns:
			float: probability density function output
		"""

        return (1.0 / (self.std * math.sqrt(2*math.pi))) * math.exp(-0.5*((x - self.mean) / self.std) ** 2)


    def plot_histogram_pdf(self, n_spaces: int):

        """Function to plot the normalized histogram of the data and a plot of the 
		probability density function along the same range
		
		Args:
			n_spaces (int): number of data points 
		
		Returns:
			list: x values for the pdf plot
			list: y values for the pdf plot
			
		"""

        mu = self.mean
        sigma = self.std

        min_range = min (self.data)
        max_range = max (self.data)

        interval = 1.0 * (max_range - min_range) / n_spaces

        x = []
        y = []

        for i in range(n_spaces):
            tmp = min_range + interval * i
            x.append(tmp)
            y.append(self.pdf(tmp))


        fig, axes = plt.subplots(2, sharex=True)
        fig.subplots_adjust(hspace=.5)
        axes[0].hist(self.data, density = True)
        axes[0].set_title('Normed Histogram of Data')
        axes[0].set_ylabel('Density')

        axes[1].plot(x, y)
        axes[1].set_title('Normed Distribution for sample mean and sample standard deviation')
        axes[1].set_ylabel('Density')

        plt.show()

        return x, y
