import bpy
import urllib.request, json, shutil
from pathlib import Path
from bpy.props import (EnumProperty, FloatProperty, IntProperty, BoolProperty, StringProperty)
from bpy_extras.io_utils import ImportHelper
from . import bl_info, my_globals, nodes, utils
from typing import Dict

latest_checked_version_is_newer = None
latest_checked_version = None
latest_version_release_date = None
error_occured_during_version_checking = None


class PackDetails:
	def __init__(self, version_required):
		self.version_required = version_required
		self.version_minor_installed = None
		self.version_installed = None


packs: Dict[str, PackDetails] = {
	"Terrains": PackDetails(version_required=2),
	"Vegetation": PackDetails(version_required=1),
	"City": PackDetails(version_required=2),
}


class SC_OT_check_latest_version(bpy.types.Operator):
	bl_idname = 'scene.sc_check_latest_version'
	bl_description = "If you want to know if there's a new version released since your current version"
	bl_label = 'Check new version'

	def execute(self, context):
		global error_occured_during_version_checking
		global latest_checked_version_is_newer
		global latest_checked_version
		global latest_version_release_date
		error_occured_during_version_checking = False
		latest_checked_version_is_newer = None
		latest_checked_version = None
		latest_version_release_date = None
		try:
			with urllib.request.urlopen("https://www.cgchan.com/static/scenecity_info.json") as url:
				data = json.loads(url.read().decode())
				latest_checked_version = data['latest_version']['number']
				latest_version_release_date = data['latest_version']['release_date']
				version_major_latest, version_minor_latest, version_bugfix_latest = latest_checked_version.split('.')
				version_major_current, version_minor_current, version_bugfix_current = bl_info['version']
				latest_checked_version_is_newer = False

				if int(version_major_latest) > int(version_major_current):
					latest_checked_version_is_newer = True
				elif int(version_major_latest) == int(version_major_current):
					if int(version_minor_latest) > int(version_minor_current):
						latest_checked_version_is_newer = True
					elif int(version_minor_latest) == int(version_minor_current):
						if int(version_bugfix_latest) > int(version_bugfix_current):
							latest_checked_version_is_newer = True

		except Exception as e:
			error_occured_during_version_checking = True
			print(e)
		return {'FINISHED'}


# def get_hotkey_entry_item(km, kmi_name, kmi_value):
# 	'''
# 	returns hotkey of specific type, with specific properties.name (keymap is not a dict, so referencing by keys is not enough
# 	if there are multiple hotkeys!)
# 	'''
# 	for i, km_item in enumerate(km.keymap_items):
# 		if km.keymap_items.keys()[i] == kmi_name:
# 			if km.keymap_items[i].properties.name == kmi_value:
# 				return km_item
# 	return None


addon_keymaps = []


# def add_hotkey():
# 	user_preferences = bpy.context.user_preferences
# 	addon_prefs = user_preferences.addons[__name__].preferences
#
# 	wm = bpy.context.window_manager
# 	kc = wm.keyconfigs.addon
# 	km = kc.keymaps.new(name="3D View Generic", space_type='VIEW_3D', region_type='WINDOW')
# 	kmi = km.keymap_items.new("wm.call_menu_pie", 'RIGHTMOUSE', 'PRESS', shift=True, ctrl=True, alt=True)
# 	kmi.properties.name = "pie.test_pie_menu"
# 	kmi.active = True
# 	addon_keymaps.append((km, kmi))
#
#
# class Template_Add_Hotkey(bpy.types.Operator):
# 	''' Add hotkey entry '''
# 	bl_idname = "template.add_hotkey"
# 	bl_label = "Addon Preferences Example"
# 	bl_options = {'REGISTER', 'INTERNAL'}
#
# 	def execute(self, context):
# 		add_hotkey()
#
# 		self.report({'INFO'}, "Hotkey added in User Preferences -> Input -> Screen -> Screen (Global)")
# 		return {'FINISHED'}


# def remove_hotkey():
# 	''' clears all addon level keymap hotkeys stored in addon_keymaps '''
# 	wm = bpy.context.window_manager
# 	kc = wm.keyconfigs.addon
# 	km = kc.keymaps['3D View Generic']
#
# 	for km, kmi in addon_keymaps:
# 		km.keymap_items.remove(kmi)
# 		wm.keyconfigs.addon.keymaps.remove(km)
# 	addon_keymaps.clear()

class SC_OT_install_or_update_pack(bpy.types.Operator, ImportHelper):
	bl_idname = 'sc_op.manage_pack'
	bl_description = 'Open file browser'
	bl_label = 'Choose file'
	# filename_ext = '.html'
	# filename_ext: bpy.props.StringProperty(
	# 	default=".html",
	# )
	filter_glob: bpy.props.StringProperty(
		default="*.pack",
		# options={'HIDDEN'},
		maxlen=255,  # Max internal buffer length, longer would be clamped.
	)
	pack_name: StringProperty(options={'HIDDEN'}, )

	def execute(self, context):
		# pack_filepath = self.properties.filepath
		pack_filepath = self.filepath
		print("SceneCity is decompressing and installing", pack_filepath, ". This may take several seconds...")
		shutil.unpack_archive(pack_filepath, utils.get_sc_data_dir(), "xztar")
		print("Success!")
		check_pack_installed(self.pack_name)
		return {"FINISHED"}


class SC_OT_remove_pack(bpy.types.Operator):
	bl_idname = 'sc_op.remove_pack'
	bl_description = 'Remove pack from hard drive'
	bl_label = 'Remove'
	pack_name: StringProperty()

	def execute(self, context):
		print("SceneCity is removing", self.pack_name, " from your hard drive...")
		shutil.rmtree(utils.get_sc_data_dir() / self.pack_name)
		print("Success!")
		check_pack_installed(self.pack_name)
		return {"FINISHED"}


def check_pack_installed(pack_name):
	try:
		with open(Path(utils.get_sc_data_dir()) / pack_name / "info.json", "r") as f:
			json_data = json.load(f)
			packs[pack_name].version_installed = json_data["version"]
			packs[pack_name].version_minor_installed = json_data["version minor"]
	except FileNotFoundError:
		packs[pack_name].version_installed = None


for pack_name in packs.keys():
	check_pack_installed(pack_name)


# def check_pack_installed(pack_name):
# 	pass


# def check_vegetation_pack_installed():
# 	global vegetation_pack_version_installed
# 	with open(Path(utils.get_vegetation_data_dir()) / "info.json", "r") as f:
# 		json_data = json.load(f)
# 		vegetation_pack_version_installed = json_data["version"]


class SC_AddonPreferences(bpy.types.AddonPreferences):
	# bl_idname must match the addon name, use '__package__', when defining this in a submodule of a python package.
	# bl_idname = __name__
	bl_idname = __package__
	adapt_colors_to: bpy.props.EnumProperty(
		name='Your Blender theme',
		description='Is your Blender theme mostly dark or mostly light? SceneCity will try to adapt to it in some places, when color codes are used in the interface',
		items=[
			('DARK', 'Dark', 'Your chosen them is mostly dark'),
			('LIGHT', 'Light', 'Your chosen them is mostly light'),
		])

	def draw(self, context):
		layout = self.layout

		box = layout.box()
		box.label(text="To install SceneCity 1) Install and enable addon 2) Install data packs ↓")
		box.label(text="To remove SC 1) Remove packs↓ 2) Disable SC 3) Restart Blender with SC disabled 4) Remove")
		box.label(text="To update SC 1) Remove it↑ but keep packs↓ 2) Install new version 3) Check if packs need updating")

		row = layout.row()
		row.operator("wm.url_open", text="Open home page").url = "https://www.cgchan.com/"

		# wm = bpy.context.window_manager
		# kc = wm.keyconfigs.user
		# km = kc.keymaps['3D View Generic']
		# kmi = get_hotkey_entry_item(km, 'wm.call_menu_pie', 'pie.test_pie_menu')
		# if kmi:
		# 	layout.context_pointer_set("keymap", km)
		# 	rna_keymap_ui.draw_kmi([], kc, km, kmi, layout, 0)
		# else:
		# 	layout.label(text="No hotkey entry found")
		# 	layout.operator(Template_Add_Hotkey.bl_idname, text="Add hotkey entry")

		# version checking
		row.operator(SC_OT_check_latest_version.bl_idname)
		if error_occured_during_version_checking:
			layout.label(text='Error. Check your internet connexion, see the console, or check the website', icon='ERROR')
		if latest_checked_version_is_newer is None:
			pass
		elif latest_checked_version_is_newer:
			layout.label(text='A newer version is available: ' + latest_checked_version + ', released: ' + latest_version_release_date, icon='INFO')
		else:
			layout.label(text='All good, you have the latest version!', icon_value=my_globals.icônes['tick'].icon_id)

		layout.prop(self, 'adapt_colors_to')

		# DATA PACKS
		box = layout.box()
		box.label(text=f"Data packs (to be installed in {utils.get_sc_data_dir()}, do not modifiy directly)", icon="PACKAGE")

		def display_data_pack_status(pack_name):
			# check_pack_installed(pack_name)
			pack_version_installed = packs[pack_name].version_installed
			pack_version_required = packs[pack_name].version_required
			pack_version_minor = packs[pack_name].version_minor_installed
			if pack_version_installed == None:
				split = box.split(factor=.8)
				split.label(text=f"{pack_name} pack not installed. Download and install v{pack_version_required}", icon="CHECKBOX_DEHLT")
				op = split.operator(SC_OT_install_or_update_pack.bl_idname, icon="FILEBROWSER", text="Install")
				op.pack_name = pack_name
			# op.filter_glob = "Vegetation v1.pack"
			elif pack_version_installed < pack_version_required or pack_version_installed > pack_version_required:
				split = box.split(factor=.8)
				split.label(
					text=f"{pack_name} pack installed but incorrect version (v{pack_version_installed}) Download and install v{pack_version_required}",
					icon="CHECKBOX_DEHLT")
				# op = split.operator(SC_OT_install_or_update_pack.bl_idname, icon="FILEBROWSER", text=f"Change to v{pack_version_required}")
				op = split.operator(SC_OT_remove_pack.bl_idname, text="Remove")
				op.pack_name = pack_name
			# op.operation = "UPDATE"
			elif pack_version_installed == pack_version_required:
				split = box.split(factor=.8)
				split.label(text=f"{pack_name} pack installed (v{pack_version_required}.{pack_version_minor})", icon="CHECKBOX_HLT")
				op = split.operator(SC_OT_remove_pack.bl_idname, text="Remove")
				op.pack_name = pack_name

		for pack_name in packs.keys():
			display_data_pack_status(pack_name)


# Vegetation data pack
# split = box.split(factor=.85)
# split.label(text=f"Vegetation data pack not installed. Download and install v{vegetation_pack_version_needed}", icon="ERROR")
# op = split.operator(SC_OT_install_pack.bl_idname, icon="FILEBROWSER", text="Install")
# op.pack_name = "vegetation"


class SC_OT_Execute_Graphs(bpy.types.Operator):
	# bl_idname = 'sc_op.chjb6rncs3eciivdkkt1'
	bl_idname = 'sc.bidule'
	bl_description = ''
	bl_label = ''

	# bl_options = {'REGISTER', 'UNDO'}

	def execute(self, context):
		# print('hey')
		for city_graph in [node_group for node_group in bpy.data.node_groups if node_group.bl_idname == nodes.SC_NodeTree.bl_idname]:
			for execute_node in [node for node in city_graph.nodes if node.bl_idname == nodes.ExecuteNode.bl_idname and node.execute_with_key_shortcut]:
				# bpy.ops.sc_op.ptpezd1wnda543t1348y(source_node_path=f"bpy.data.node_groups['{city_graph.name}'].nodes['{execute_node.name}']",
				# 	node_method_name_to_call='get_sc_bldata')
				bpy.ops.sc_op.ptpezd1wnda543t1348y(source_node_path=f"bpy.data.node_groups['{city_graph.name}'].nodes['{execute_node.name}']")

		return {'FINISHED'}


def register_keymaps():
	wm = bpy.context.window_manager
	km = wm.keyconfigs.addon.keymaps.new(name="Window", space_type='EMPTY', region_type='WINDOW')
	# kmi = km.keymap_items.new("wm.call_menu_pie", type="E", alt=True, value="PRESS")
	kmi = km.keymap_items.new(SC_OT_Execute_Graphs.bl_idname, type="E", shift=True, alt=False, ctrl=True, value="PRESS")
	# kmi.properties.name = "editor_switcher_pie_menu"
	addon_keymaps.append(km)


def unregister_keymaps():
	wm = bpy.context.window_manager
	for km in addon_keymaps:
		for kmi in km.keymap_items:
			km.keymap_items.remove(kmi)
		wm.keyconfigs.addon.keymaps.remove(km)
	addon_keymaps.clear()


def register():
	register_keymaps()


def unregister():
	unregister_keymaps()

	# remove_hotkey()
	# handle the keymap
	wm = bpy.context.window_manager
	for km in addon_keymaps:
		wm.keyconfigs.addon.keymaps.remove(km)
# clear the list
# addon_keymaps.clear()
