import bpy
import random, time
from . import Node, Grid, GridGetter, SC_Operator, SOCKET_Grid
from ..utils import définirPixel


class GridNode(bpy.types.Node, Node, GridGetter):
	bl_idname = 'sc_node_r4uhwrd61uxtkqtr900e'
	bl_label = 'Grid'
	at_least_one_input_socket_required = False

	grid_size: bpy.props.IntVectorProperty(
		name='Grid size',
		description='Number of cells on x and on y',
		size=2,
		min=1,
		default=(100, 100))
	cell_size: bpy.props.FloatProperty(
		name='Cell size',
		description='Size on each cell in the grid, in Blender units',
		min=.001,
		default=10)

	def sc_init(self, context):
		self.width = 250
		# self.outputs.new('GridSocket', 'Grid')
		self.create_output(SOCKET_Grid)

	def sc_draw_buttons(self, context, layout):
		# self.ui_display_doc_and_last_job_done2(layout)
		layout.prop(self, 'grid_size')
		layout.prop(self, 'cell_size')

	# @Node.get_data_first
	def get_grid(self, *args, **kwargs):
		# raise ValueError
		return Grid(self.grid_size, self.cell_size)


class KeyValueColorProperty(bpy.types.PropertyGroup):
	key_value: bpy.props.StringProperty(
		name='Key / value',
		description='The key and associated value stored in the grid that this color will correspond to. Leading and trailing spaces will be trimmed')
	color: bpy.props.FloatVectorProperty(
		name='Color',
		description='The color of the cells that have this key / value',
		default=(0, 0, 0, 1),
		size=4,
		min=0, max=1, subtype='COLOR')


class GridToBlenderImageNode(bpy.types.Node, Node):
	bl_idname = 'sc_node_yxtbovx2dcew34ozmkl1'
	bl_label = 'Grid to Blender image'
	random_seed: bpy.props.IntProperty(
		name='Seed',
		description='Random seed', )
	image_name: bpy.props.StringProperty(
		name='Image name',
		description='Name of the ouput image to draw into',
		default='SceneCity grid')
	keys_values_colors: bpy.props.CollectionProperty(type=KeyValueColorProperty)

	def sc_init(self, context):
		# self.keys_values_colors.add()
		self.width = 300
		self.random_seed = random.randint(0, 9e5)
		# self.inputs.new('GridSocket', 'Grid')
		self.create_input(SOCKET_Grid, is_required=True)

	def sc_draw_buttons(self, context, layout):
		# if len(self.inputs['Grid'].links) <= 0:
		# 	layout.label(text='Input grid needed', icon='ERROR')
		# self.ui_display_doc_and_last_job_done2(layout)
		# row = layout.row()
		# row.prop(self, 'random_seed')
		# op = row.operator('node.randomize_seed_operator')
		# op.source_node_path = 'bpy.data.node_groups["' + self.id_data.name + '"].' + self.path_from_id()

		layout.prop(self, 'image_name', icon='FILE_IMAGE')

		op = layout.operator(SC_OT_Grid2BlenderImageNode_AddColor.bl_idname)
		op.source_node_path = 'bpy.data.node_groups["' + self.id_data.name + '"].' + self.path_from_id()
		for i, key_value in enumerate(self.keys_values_colors):
			# row = layout.row()
			split = layout.split(factor=.75)
			split.prop(key_value, 'key_value')
			split.prop(key_value, 'color', text='')
			op = split.operator(SC_OT_Grid2BlenderImageNode_DeleteColor.bl_idname)
			op.source_node_path = 'bpy.data.node_groups["' + self.id_data.name + '"].' + self.path_from_id()
			op.index = i

		op: SC_OT_Grid2BlenderImageNode_Draw = layout.operator(SC_OT_Grid2BlenderImageNode_Draw.bl_idname)
		op.source_node_path = 'bpy.data.node_groups["' + self.id_data.name + '"].' + self.path_from_id()


# op.truc = 'r'


class SC_OT_Grid2BlenderImageNode_AddColor(bpy.types.Operator, SC_Operator):
	bl_idname = 'sc.grid_2_blender_image_node_add_color'
	bl_label = 'Add new color'
	bl_description = 'Add a new color for a key / value pair stored in the grid to draw'

	# def SC_execute(self, source_node: GridToBlenderImageNode):
	def execute(self, context):
		source_node: GridToBlenderImageNode = eval(self.source_node_path)
		source_node.keys_values_colors.add()
		return {'FINISHED'}


class SC_OT_Grid2BlenderImageNode_DeleteColor(bpy.types.Operator, SC_Operator):
	bl_idname = 'sc.grid_2_blender_image_node_delete_color'
	bl_label = 'X'
	bl_description = 'Delete this color'
	index: bpy.props.IntProperty()

	# def SC_execute(self, source_node: GridToBlenderImageNode):
	# 	source_node.keys_values_colors.remove(self.index)

	def execute(self, context):
		source_node: GridToBlenderImageNode = eval(self.source_node_path)
		source_node.keys_values_colors.remove(self.index)
		return {'FINISHED'}


class SC_OT_Grid2BlenderImageNode_Draw(bpy.types.Operator, SC_Operator):
	bl_idname = 'sc.grid_2_blender_image_node_draw'
	bl_description = ''
	bl_label = 'Create / update image'

	# def get_data_for_execution(self, source_node: GridToBlenderImageNode):
	# 	grid_source: GridGetter = source_node.inputs['Grid'].links[0].from_node
	# 	return grid_source.get_grid()

	# def SC_execute(self, source_node: GridToBlenderImageNode, grid: Grid):
	def execute(self, context):

		source_node: GridToBlenderImageNode = eval(self.source_node_path)
		grid_source: GridGetter = source_node.inputs[0].links[0].from_node
		grid: Grid = grid_source.get_grid()

		# get or create new image
		try:
			image = bpy.data.images[source_node.image_name]
			image.scale(grid.grid_size[0], grid.grid_size[1])
		except:
			image = bpy.data.images.new(
				source_node.image_name,
				grid.grid_size[0],
				grid.grid_size[1],
				alpha=True,
				float_buffer=True)
			image.name = source_node.image_name  # force name
		pixels = [0 for _ in range(grid.grid_size[0] * grid.grid_size[1] * 4)]
		colors_per_key_value = {}
		for key_value_color in source_node.keys_values_colors:
			key, value = key_value_color.key_value.split('=')
			key = key.strip()
			value = value.strip()
			color = (key_value_color.color[0], key_value_color.color[1], key_value_color.color[2], key_value_color.color[3])
			colors_per_key_value[(key, value)] = color
		# print(colors_per_key_value)
		# colors_per_value = [
		# 	(1, 1, .25, 1),
		# 	(.25, 1, .25, 1),
		# 	(.25, .25, 1, 1),
		# 	(0, 0, 0, 1),
		# ]
		for i in range(grid.grid_size[0]):
			for j in range(grid.grid_size[1]):
				cell = grid.data[i][j]
				# print(cell)
				for key, value in cell.items():
					try:
						color = colors_per_key_value[(key, value)]
						définirPixel(pixels, grid.grid_size[0], i, j, color)
						break
					except KeyError:
						continue
		# définirPixel(pixels, grid.grid_size[0], i, j, (1, 0, 1, 1))
		image.pixels = pixels
		image.update()
		return {'FINISHED'}
