import types
import numpy as np
import matplotlib.pyplot as plt
from pyH2A.Utilities.output_utilities import make_bold, millify, bottom_offset, Figure_Lean
from pyH2A.Discounted_Cash_Flow import Discounted_Cash_Flow

class Cost_Contributions_Analysis:
	'''Reading cost contributions from DCF output and plotting it.

	Notes
	-----
	`Cost_Contributions_Analysis` does not require any input, it is sufficient
	to include "# Cost_Contributions_Analysis" in input file.
	Contributions for plotting have to provided as a dictionary with three components:
	`Data` containing the name and value for each contribution.
	`Total` containing the total value
	`Table Group`, containing the name of overarching group of values, which are shown. 
	Dictionaries with this structure can be automatically generated by ``sum_all_tables`` 
	function.
	If the name of a contribution contains a '-', the string will be split and only the part after the
	'-' will be displayed.
	'''

	def __init__(self, input_file):
		self.base_case = Discounted_Cash_Flow(input_file, print_info = False)

	def cost_breakdown_plot(self, ax = None, figure_lean = True,
							plugin = None, plugin_property = None,
							label_offset = 5.5, x_label_string = 'Cost / USD',
							x_label_string_H2 = r'Levelized cost / USD per kg $H_{2}$',
							plot_kwargs = {}, **kwargs):
		'''Plotting cost breakdown plot.

		Parameters
		----------
		ax : matplotlib.axes, optional
			Axes object in which plot is drawn. Default is None, creating new plot.
		figure_lean : bool, optional
			If figure_lean is True, matplotlib.fig object is returned.
		plugin : str or None, optional
			Selection of plugin from which contributions data is to be read. If None,
			defaults to overall H2 cost contributions.
		plugin_property: str or None, optional
			Specific property of plugin from which contributions data is to be read.
		label_offset : float, optional
			Offset for contributions labels.
		x_label_string : str, optional
			String for x axis label.
		x_label_string_H2 : str, optional
			String for x axis label when overall H2 cost breakdown is plotted
		plot_kwargs: dict, optional
			Dictionary containing optional keyword arguments for
			:func:`~pyH2A.Utilities.output_utilities.Figure_Lean`, has priority over `**kwargs`.
		**kwargs: 
			Additional `kwargs` passed to 
			:func:`~pyH2A.Utilities.output_utilities.Figure_Lean`

		Returns 
		-------
		figure : matplotlib.fig or None
			matplotlib.fig is returned if `figure_lean` is True.

		Notes
		-----
		Names of contributions are split at '-' symbols and only the last
		part is displayed. For example: `Direct Capital Costs - Installation`
		is displayed only as `Installation`.
		'''

		kwargs = {**{'left': 0.4, 'top': 0.96, 
					 'name': 'Cost_Breakdown_Plot'}, 
				  **kwargs, **plot_kwargs}

		if ax is None:
			figure = Figure_Lean(**kwargs)
			ax = figure.ax

		if plugin is None:
			self.contributions = self.base_case.contributions
			self.data = self.base_case.contributions['Data']
		else:
			selected_plugin = self.base_case.plugs[plugin]
			self.contributions = getattr(selected_plugin, plugin_property)
			self.data = self.contributions['Data']

		sorted_keys = sorted(self.data, key = self.data.get)
		sorted_contributions = {}

		for key in sorted_keys:
			sorted_contributions[key] = self.data[key]
		
		cmap = plt.get_cmap('plasma')

		label_offset = self.contributions['Total'] / label_offset

		for counter, key in enumerate(sorted_contributions):
			if '-' in key:
				name = key.split('-')[1].strip(' ')
			else:
				name = key

			value = sorted_contributions[key]

			color_value = counter / len(sorted_contributions)
			ax.barh(name, sorted_contributions[key], 
				    color = cmap(color_value), zorder = 5)
			ax.annotate(millify(value), xy = (max(value, 0) + label_offset, counter), 
						va = 'center', ha = 'center')

		ax.barh(make_bold(self.contributions['Table Group']), 
						  self.contributions['Total'], 
						  color = 'darkgreen', zorder = 5)
		ax.annotate(millify(self.contributions['Total']), 
							xy = (self.contributions['Total'] + label_offset, 
								  len(sorted_contributions)), 
							va = 'center', ha = 'center')

		if self.contributions['Table Group'] == 'Total cost of hydrogen':
			x_label_string = x_label_string_H2

		ax.set_xlabel(x_label_string)

		xlim = np.asarray(ax.get_xlim())
		xlim[1] += 2 * label_offset
		ax.set_xlim(xlim)
	
		ax.ticklabel_format(axis = 'x', style = 'sci', scilimits = (0,0), useMathText = True)
		ax.xaxis._update_offset_text_position = types.MethodType(bottom_offset, ax.xaxis)

		ax.grid(color = 'grey', linestyle = '--', linewidth = 0.2, zorder = 0)

		if figure_lean is True:
			figure.execute()
			return figure.fig

