import obspython as obs

total_seconds = 0
source_name   = ""

cur_seconds   = 0
last_text     = ""
stop_text     = ""
show_hours	  = False
activated     = False

hotkey_id     = ""
hotkey_save_array = []

def set_time_text():

	global cur_seconds
	global stop_text
	global activated
	global last_text
	global show_hours

	seconds       = cur_seconds % 60
	total_minutes = cur_seconds // 60
	minutes       = total_minutes % 60
	hours         = total_minutes // 60
	text          = ''
	
	if show_hours:
		text = '{:02d}:'.format(hours)
	text += '{:02d}:{:02d}'.format(minutes, seconds)
	
	if cur_seconds < 1:
		text = stop_text
		
	if text != last_text:
		last_text = text
		source = obs.obs_get_source_by_name(source_name)
		if source is not None:
			settings = obs.obs_data_create()
			settings = obs.obs_data_create()
			obs.obs_data_set_string(settings, "text", text)
			obs.obs_source_update(source, settings)
			obs.obs_data_release(settings)
			obs.obs_source_release(source)
	
def timer_callback():
	global cur_seconds

	if cur_seconds > 0:
		cur_seconds -= 1
	else:
		obs.remove_current_callback()

	set_time_text()

def activate(activating):
	global cur_seconds
	global activated

	if activated != activating:
		activated = activating
		if activating:
			cur_seconds = total_seconds
			set_time_text()
			obs.timer_add(timer_callback, 1000)
		else:
			obs.timer_remove(timer_callback)

def activate_signal(cd, activating):
	source = obs.calldata_source(cd, "source")
	if source is not None:
		name = obs.obs_source_get_name(source)
		if name == source_name:
			activate(activating)

def source_activated(cd):
	activate_signal(cd, True)
	
def source_deactivated(cd):
	activate_signal(cd, False)

def reset(pressed):
	if not pressed:
		return

	activate(False)
	source = obs.obs_get_source_by_name(source_name)
	if source is not None:
		active = obs.obs_source_active(source)
		obs.obs_source_release(source)
		activate(active)

def reset_button_clicked(props, p):
	reset(True)
	return False

#----------------------------------------------------------

# A function named script_properties defines the properties that the user
# can change for the entire script module itself
def script_properties():
	props = obs.obs_properties_create()
	obs.obs_properties_add_int(props, "duration", "Duration (minutes)", 1, 100000, 1)

	p = obs.obs_properties_add_list(props, "source", "Text Source", obs.OBS_COMBO_TYPE_EDITABLE, obs.OBS_COMBO_FORMAT_STRING)
	sources = obs.obs_enum_sources()
	if sources is not None:
		for source in sources:
			source_id = obs.obs_source_get_id(source)
			if source_id == "text_gdiplus" or source_id == "text_ft2_source":
				name = obs.obs_source_get_name(source)
				obs.obs_property_list_add_string(p, name, name)
	obs.source_list_release(sources)

	obs.obs_properties_add_bool(props, "show_hours", "Show hours?")
	obs.obs_properties_add_text(props, "stop_text", "Final Text", obs.OBS_TEXT_DEFAULT)
	obs.obs_properties_add_button(props, "reset_button", "Reset Timer", reset_button_clicked)

	return props

# A function named script_description returns the description shown to the user
def script_description():
	return '''Sets a text source to act as a countdown timer when the source is active.
	
Original lua script by Jim, python translation and enhancements by AKrumbach'''


# A function named script_update will be called when settings are changed
def script_update(settings):
	global total_seconds
	global source_name
	global stop_text
	global show_hours

	activate(False)

	total_seconds = obs.obs_data_get_int(settings, "duration") * 60
	source_name = obs.obs_data_get_string(settings, "source")
	stop_text = obs.obs_data_get_string(settings, "stop_text")
	show_hours = obs.obs_data_get_bool(settings, "show_hours")

	reset(True)

# A function named script_defaults will be called to set the default settings
def script_defaults(settings):
	obs.obs_data_set_default_bool(settings, "show_hours", True)
	obs.obs_data_set_default_int(settings, "duration", 5)
	obs.obs_data_set_default_string(settings, "stop_text", "Starting soon (tm)")

# A function named script_save will be called when the script is saved
#
# NOTE: This function is usually used for saving extra data (such as in this
# case, a hotkey's save data).  Settings set via the properties are saved automatically.
def script_save(settings):
	hotkey_save_array = obs.obs_hotkey_save(hotkey_id)
	obs.obs_data_set_array(settings, "reset_hotkey", hotkey_save_array)
	obs.obs_data_array_release(hotkey_save_array)

# a function named script_load will be called on startup
def script_load(settings):
	# Connect hotkey and activation/deactivation signal callbacks
	#
	# NOTE: These particular script callbacks do not necessarily have to
	# be disconnected, as callbacks will automatically destroy themselves
	# if the script is unloaded.  So there's no real need to manually
	# disconnect callbacks that are intended to last until the script is
	# unloaded.
	
	global hotkey_id
	global hotkey_save_array
	
	sh = obs.obs_get_signal_handler()
#	obs.signal_handler_connect(sh, "starting", source_activated)
#	obs.signal_handler_connect(sh, "stopping", source_deactivated)
	obs.signal_handler_connect(sh, "source_activate", source_activated)
	obs.signal_handler_connect(sh, "source_deactivate", source_deactivated)
#	obs.signal_handler_connect_global(sh, record_signals)

	hotkey_id = obs.obs_hotkey_register_frontend("reset_timer_thingy", "Reset Timer", reset)
	
	hotkey_save_array = obs.obs_data_get_array(settings, "reset_hotkey")
	obs.obs_hotkey_load(hotkey_id, hotkey_save_array)
	obs.obs_data_array_release(hotkey_save_array)