import matplotlib.pyplot as plt
import matplotlib as mpl
import numpy as np
import copy

from core_tools.utility.plotting.plot_settings import plot_layout, graph_settings_1D, _1D_raw_plot_data
from core_tools.utility.plotting.plot_general import _data_plotter

class plotter_1D(_data_plotter):
	def __init__(self, plt_layout = plot_layout(), graph_setings = graph_settings_1D()):
		self.plot_layout = plt_layout
		self.local_data = np.empty([plt_layout.n_plots_y, plt_layout.n_plots_x], dtype = _1D_plot_single)

		for i in range(self.local_data.size):
			self.local_data.flat[i] = _1D_plot_single(graph_setings)

class _1D_plot_single:
	def __init__(self, graph_settings):
		self.settings = copy.copy(graph_settings) #default settings
		self.data     = []
		self.x_lim    = None
		self.y_lim    = None

	def set_labels(self, xlabel, ylabel):
		self.settings.xlabel = xlabel
		self.settings.ylabel = ylabel

	def set_range(self, x_range=None, y_range=None):
		if x_range is not None:
			self.x_lim = x_range
		if y_range is not None:
			self.y_lim = y_range


	def add_data(self, x, y, xerr = None, yerr = None, label = None, settings = None, w=None, c=None, alpha=None):
		if settings == None:
			settings = copy.copy(self.settings)
		else:
			settings = copy.copy(settings)
		if label is not None:
			settings.label = label
		if w is not None:
			if 'l' not in w:
				settings.linestyle  = ''
			if 'p' in w:
				settings.marker = 'o'
		if c is not None:
			settings.color = c
		if alpha is not None:
			settings.alpha = alpha

		self.data += [_1D_raw_plot_data(x,y, xerr, yerr, settings)]

	def _render(self, ax, layout_settings, index, scaler = 1, figure=None):
		ax.locator_params(axis='x', nbins=layout_settings.xbins)
		ax.locator_params(axis='y', nbins=layout_settings.ybins)
	

		ax.xaxis.set_minor_locator(mpl.ticker.AutoMinorLocator())
		ax.yaxis.set_minor_locator(mpl.ticker.AutoMinorLocator())
		
		ax.tick_params(direction='in', which='both', top=True, right=True)
		if self.settings.xlog == True:
			ax.set_xscale('log')
		if self.settings.ylog == True:
			ax.set_yscale('log')

		if self.x_lim is not None:
			ax.set_xlim(*self.x_lim)
		if self.y_lim is not None:
			ax.set_ylim(*self.y_lim)

		labels = False
		for i in range(len(self.data)):
			data = self.data[i]
			if data.x_error == None and data.y_error == None:
				ax.plot(data.x_data, data.y_data, **data.settings.plot_settings_to_dict(i, scaler))
			else:
				pass
				# ax.errorbar(a, c, yerr = b/10,ecolor='g',linewidth=1.2,elinewidth=0.7)
			if data.settings.label is not None:
				labels = True

		if self.settings.xlabel is not None:
			if layout_settings.share_x == False:
				ax.set_xlabel(self.settings.xlabel)
			elif index[0] == layout_settings.n_plots_x-1 :
				ax.set_xlabel(self.settings.xlabel)

		if self.settings.ylabel is not None:
			if layout_settings.share_y == False:
				ax.set_ylabel(self.settings.ylabel)
			elif index[1] == 0 :
				ax.set_ylabel(self.settings.ylabel)

		if labels == True:
			ax.legend()

# TODO add log scale support !!!


if __name__ == '__main__':

	from colors import MATERIAL_COLOR, Red

	# global settings
	g = graph_settings_1D()
	g.color = Red[::-1]
	g.linewidth = 1

	a = plotter_1D(graph_setings=g)
	a[0].set_labels('x_label', 'y_label')
	a[0].add_data(np.linspace(0,50,200), np.sin(np.linspace(10,50,200)), w = 'p', alpha = 1, c=Red[5])
	a[0].add_data(np.linspace(0,50,200), np.sin(np.linspace(10,50,200)), w = 'l', alpha = 0.3, c=Red[5])

	# a.plot()
	a.save('test1D_single.svg')

	a = plotter_1D(plot_layout(n_plots_x = 1,n_plots_y = 2))

	a[0].set_labels('x_label', 'y_label')
	a[0].add_data(np.linspace(10,50,50), np.random.random([50]))

	a[0,1].set_labels('x_label', 'y_label')
	a[0,1].add_data(np.linspace(10,50,50), np.random.random([50]))

	a.save('test1D_12.svg')
	# a.plot()


	a = plotter_1D(plot_layout(n_plots_x = 2,n_plots_y = 2, share_x=True, share_y=True))

	a[0].set_labels('x_label', 'y_label')
	a[0].add_data(np.linspace(10,50,50), np.random.random([50]), label='test 1')

	a[0,1].set_labels('x_label', 'y_label')
	a[0,1].add_data(np.linspace(10,50,50), np.random.random([50]), label='test 2')
	a[0,1].add_data(np.linspace(10,50,50), np.random.random([50]))

	a[1,0].set_labels('x_label', 'y_label')
	a[1,0].add_data(np.linspace(10,50,50), np.random.random([50]))

	a[1,1].set_labels('x_label', 'y_label')
	a[1,1].add_data(np.linspace(10,50,50), np.sin(np.linspace(10,50,50)))
	a.save('test1D_22.svg')
	# a.plot()

	
	a = plotter_1D(plot_layout((300, 70), n_plots_x = 6,n_plots_y = 1, share_x=False, share_y=True))

	a[0].set_labels('time (ns)', 'Spin up probably (%)')
	a[0].add_data(np.linspace(0,500,50), np.sin(np.linspace(10,50,50)))

	a[1].set_labels('time (ns)', 'Spin up probably (%)')
	a[1].add_data(np.linspace(0,500,50), np.sin(np.linspace(10,50,50)))

	a[2].set_labels('time (ns)', 'Spin up probably (%)')
	a[2].add_data(np.linspace(0,500,50), np.sin(np.linspace(10,50,50)))

	a[3].set_labels('time (ns)', 'Spin up probably (%)')
	a[3].add_data(np.linspace(0,500,50), np.sin(np.linspace(10,50,50)))

	a[4].set_labels('time (ns)', 'Spin up probably (%)')
	a[4].add_data(np.linspace(0,500,50), np.sin(np.linspace(10,50,50)))

	a[5].set_labels('time (ns)', 'Spin up probably (%)')
	a[5].add_data(np.linspace(0,500,50), np.sin(np.linspace(10,50,50)))
	print(a)
	a.save('test1D_61.svg')

	a.plot()
[((107, 5, 107, 24), 'core_tools.utility.plotting.plot_settings.graph_settings_1D', 'graph_settings_1D', ({}, {}), '()', False, 'from core_tools.utility.plotting.plot_settings import plot_layout, graph_settings_1D, _1D_raw_plot_data\n'), ((10, 33, 10, 46), 'core_tools.utility.plotting.plot_settings.plot_layout', 'plot_layout', ({}, {}), '()', False, 'from core_tools.utility.plotting.plot_settings import plot_layout, graph_settings_1D, _1D_raw_plot_data\n'), ((10, 64, 10, 83), 'core_tools.utility.plotting.plot_settings.graph_settings_1D', 'graph_settings_1D', ({}, {}), '()', False, 'from core_tools.utility.plotting.plot_settings import plot_layout, graph_settings_1D, _1D_raw_plot_data\n'), ((12, 20, 12, 99), 'numpy.empty', 'np.empty', (), '', True, 'import numpy as np\n'), ((19, 18, 19, 43), 'copy.copy', 'copy.copy', ({(19, 28, 19, 42): 'graph_settings'}, {}), '(graph_settings)', False, 'import copy\n'), ((113, 15, 113, 36), 'numpy.linspace', 'np.linspace', ({(113, 27, 113, 28): '(0)', (113, 29, 113, 31): '(50)', (113, 32, 113, 35): '(200)'}, {}), '(0, 50, 200)', True, 'import numpy as np\n'), ((114, 15, 114, 36), 'numpy.linspace', 'np.linspace', ({(114, 27, 114, 28): '(0)', (114, 29, 114, 31): '(50)', (114, 32, 114, 35): '(200)'}, {}), '(0, 50, 200)', True, 'import numpy as np\n'), ((119, 16, 119, 56), 'core_tools.utility.plotting.plot_settings.plot_layout', 'plot_layout', (), '', False, 'from core_tools.utility.plotting.plot_settings import plot_layout, graph_settings_1D, _1D_raw_plot_data\n'), ((122, 15, 122, 36), 'numpy.linspace', 'np.linspace', ({(122, 27, 122, 29): '(10)', (122, 30, 122, 32): '(50)', (122, 33, 122, 35): '(50)'}, {}), '(10, 50, 50)', True, 'import numpy as np\n'), ((122, 38, 122, 60), 'numpy.random.random', 'np.random.random', ({(122, 55, 122, 59): '[50]'}, {}), '([50])', True, 'import numpy as np\n'), ((125, 17, 125, 38), 'numpy.linspace', 'np.linspace', ({(125, 29, 125, 31): '(10)', (125, 32, 125, 34): '(50)', (125, 35, 125, 37): '(50)'}, {}), '(10, 50, 50)', True, 'import numpy as np\n'), ((125, 40, 125, 62), 'numpy.random.random', 'np.random.random', ({(125, 57, 125, 61): '[50]'}, {}), '([50])', True, 'import numpy as np\n'), ((131, 16, 131, 84), 'core_tools.utility.plotting.plot_settings.plot_layout', 'plot_layout', (), '', False, 'from core_tools.utility.plotting.plot_settings import plot_layout, graph_settings_1D, _1D_raw_plot_data\n'), ((134, 15, 134, 36), 'numpy.linspace', 'np.linspace', ({(134, 27, 134, 29): '(10)', (134, 30, 134, 32): '(50)', (134, 33, 134, 35): '(50)'}, {}), '(10, 50, 50)', True, 'import numpy as np\n'), ((134, 38, 134, 60), 'numpy.random.random', 'np.random.random', ({(134, 55, 134, 59): '[50]'}, {}), '([50])', True, 'import numpy as np\n'), ((137, 17, 137, 38), 'numpy.linspace', 'np.linspace', ({(137, 29, 137, 31): '(10)', (137, 32, 137, 34): '(50)', (137, 35, 137, 37): '(50)'}, {}), '(10, 50, 50)', True, 'import numpy as np\n'), ((137, 40, 137, 62), 'numpy.random.random', 'np.random.random', ({(137, 57, 137, 61): '[50]'}, {}), '([50])', True, 'import numpy as np\n'), ((138, 17, 138, 38), 'numpy.linspace', 'np.linspace', ({(138, 29, 138, 31): '(10)', (138, 32, 138, 34): '(50)', (138, 35, 138, 37): '(50)'}, {}), '(10, 50, 50)', True, 'import numpy as np\n'), ((138, 40, 138, 62), 'numpy.random.random', 'np.random.random', ({(138, 57, 138, 61): '[50]'}, {}), '([50])', True, 'import numpy as np\n'), ((141, 17, 141, 38), 'numpy.linspace', 'np.linspace', ({(141, 29, 141, 31): '(10)', (141, 32, 141, 34): '(50)', (141, 35, 141, 37): '(50)'}, {}), '(10, 50, 50)', True, 'import numpy as np\n'), ((141, 40, 141, 62), 'numpy.random.random', 'np.random.random', ({(141, 57, 141, 61): '[50]'}, {}), '([50])', True, 'import numpy as np\n'), ((144, 17, 144, 38), 'numpy.linspace', 'np.linspace', ({(144, 29, 144, 31): '(10)', (144, 32, 144, 34): '(50)', (144, 35, 144, 37): '(50)'}, {}), '(10, 50, 50)', True, 'import numpy as np\n'), ((149, 16, 149, 96), 'core_tools.utility.plotting.plot_settings.plot_layout', 'plot_layout', (), '', False, 'from core_tools.utility.plotting.plot_settings import plot_layout, graph_settings_1D, _1D_raw_plot_data\n'), ((152, 15, 152, 36), 'numpy.linspace', 'np.linspace', ({(152, 27, 152, 28): '(0)', (152, 29, 152, 32): '(500)', (152, 33, 152, 35): '(50)'}, {}), '(0, 500, 50)', True, 'import numpy as np\n'), ((155, 15, 155, 36), 'numpy.linspace', 'np.linspace', ({(155, 27, 155, 28): '(0)', (155, 29, 155, 32): '(500)', (155, 33, 155, 35): '(50)'}, {}), '(0, 500, 50)', True, 'import numpy as np\n'), ((158, 15, 158, 36), 'numpy.linspace', 'np.linspace', ({(158, 27, 158, 28): '(0)', (158, 29, 158, 32): '(500)', (158, 33, 158, 35): '(50)'}, {}), '(0, 500, 50)', True, 'import numpy as np\n'), ((161, 15, 161, 36), 'numpy.linspace', 'np.linspace', ({(161, 27, 161, 28): '(0)', (161, 29, 161, 32): '(500)', (161, 33, 161, 35): '(50)'}, {}), '(0, 500, 50)', True, 'import numpy as np\n'), ((164, 15, 164, 36), 'numpy.linspace', 'np.linspace', ({(164, 27, 164, 28): '(0)', (164, 29, 164, 32): '(500)', (164, 33, 164, 35): '(50)'}, {}), '(0, 500, 50)', True, 'import numpy as np\n'), ((167, 15, 167, 36), 'numpy.linspace', 'np.linspace', ({(167, 27, 167, 28): '(0)', (167, 29, 167, 32): '(500)', (167, 33, 167, 35): '(50)'}, {}), '(0, 500, 50)', True, 'import numpy as np\n'), ((37, 14, 37, 38), 'copy.copy', 'copy.copy', ({(37, 24, 37, 37): 'self.settings'}, {}), '(self.settings)', False, 'import copy\n'), ((39, 14, 39, 33), 'copy.copy', 'copy.copy', ({(39, 24, 39, 32): 'settings'}, {}), '(settings)', False, 'import copy\n'), ((52, 16, 52, 60), 'core_tools.utility.plotting.plot_settings._1D_raw_plot_data', '_1D_raw_plot_data', ({(52, 34, 52, 35): 'x', (52, 36, 52, 37): 'y', (52, 39, 52, 43): 'xerr', (52, 45, 52, 49): 'yerr', (52, 51, 52, 59): 'settings'}, {}), '(x, y, xerr, yerr, settings)', False, 'from core_tools.utility.plotting.plot_settings import plot_layout, graph_settings_1D, _1D_raw_plot_data\n'), ((59, 29, 59, 58), 'matplotlib.ticker.AutoMinorLocator', 'mpl.ticker.AutoMinorLocator', ({}, {}), '()', True, 'import matplotlib as mpl\n'), ((60, 29, 60, 58), 'matplotlib.ticker.AutoMinorLocator', 'mpl.ticker.AutoMinorLocator', ({}, {}), '()', True, 'import matplotlib as mpl\n'), ((113, 45, 113, 67), 'numpy.linspace', 'np.linspace', ({(113, 57, 113, 59): '(10)', (113, 60, 113, 62): '(50)', (113, 63, 113, 66): '(200)'}, {}), '(10, 50, 200)', True, 'import numpy as np\n'), ((114, 45, 114, 67), 'numpy.linspace', 'np.linspace', ({(114, 57, 114, 59): '(10)', (114, 60, 114, 62): '(50)', (114, 63, 114, 66): '(200)'}, {}), '(10, 50, 200)', True, 'import numpy as np\n'), ((144, 47, 144, 68), 'numpy.linspace', 'np.linspace', ({(144, 59, 144, 61): '(10)', (144, 62, 144, 64): '(50)', (144, 65, 144, 67): '(50)'}, {}), '(10, 50, 50)', True, 'import numpy as np\n'), ((152, 45, 152, 66), 'numpy.linspace', 'np.linspace', ({(152, 57, 152, 59): '(10)', (152, 60, 152, 62): '(50)', (152, 63, 152, 65): '(50)'}, {}), '(10, 50, 50)', True, 'import numpy as np\n'), ((155, 45, 155, 66), 'numpy.linspace', 'np.linspace', ({(155, 57, 155, 59): '(10)', (155, 60, 155, 62): '(50)', (155, 63, 155, 65): '(50)'}, {}), '(10, 50, 50)', True, 'import numpy as np\n'), ((158, 45, 158, 66), 'numpy.linspace', 'np.linspace', ({(158, 57, 158, 59): '(10)', (158, 60, 158, 62): '(50)', (158, 63, 158, 65): '(50)'}, {}), '(10, 50, 50)', True, 'import numpy as np\n'), ((161, 45, 161, 66), 'numpy.linspace', 'np.linspace', ({(161, 57, 161, 59): '(10)', (161, 60, 161, 62): '(50)', (161, 63, 161, 65): '(50)'}, {}), '(10, 50, 50)', True, 'import numpy as np\n'), ((164, 45, 164, 66), 'numpy.linspace', 'np.linspace', ({(164, 57, 164, 59): '(10)', (164, 60, 164, 62): '(50)', (164, 63, 164, 65): '(50)'}, {}), '(10, 50, 50)', True, 'import numpy as np\n'), ((167, 45, 167, 66), 'numpy.linspace', 'np.linspace', ({(167, 57, 167, 59): '(10)', (167, 60, 167, 62): '(50)', (167, 63, 167, 65): '(50)'}, {}), '(10, 50, 50)', True, 'import numpy as np\n')]