"""
Observers for running interactive programs in the terminal.
"""

#c Copyright 2008-2025, the GAVO project <gavo@ari.uni-heidelberg.de>
#c
#c This program is free software, covered by the GNU GPL.  See the
#c COPYING file in the source distribution.


import sys

from gavo import base


class StingyPlainUI(base.ObserverBase):
	"""An Observer swallowing infos, warnings, and the like.

	This is to configure the UI.  Enable it by calling
	``api.StingyPlainUI(api.ui)``.
	"""
	def __init__(self, eh):
		self.curIndent = ""
		base.ObserverBase.__init__(self, eh)

	def showMsg(self, msg):
		print(self.curIndent+msg, file=sys.stderr)

	def pushIndent(self):
		self.curIndent = self.curIndent+"  "
	
	def popIndent(self):
		self.curIndent = self.curIndent[:-2]

	@base.listensTo("SourceError")
	def announceSourceError(self, srcString):
		self.showMsg("Failed source %s"%srcString)

	@base.listensTo("Error")
	def printErrMsg(self, errMsg):
		self.showMsg("*X*X* "+errMsg)


class SemiStingyPlainUI(StingyPlainUI):
	"""A StingyPlainUI that at least displays warnings.

	This is to configure the UI.  Enable it by calling
	``api.SemiStingyPlainUI(api.ui)``.
	"""
	@base.listensTo("Warning")
	def printWarning(self, message):
		self.showMsg("** WARNING: "+message)


class PlainUI(SemiStingyPlainUI):
	"""An Observer spitting out most info to the screen.

	This is to configure the UI.  Enable it by calling ``api.PlainUI(api.ui)``.
	"""
	@base.listensTo("NewSource")
	def announceNewSource(self, srcString):
		self.showMsg("Starting %s"%srcString)
		self.pushIndent()
	
	@base.listensTo("SourceFinished")
	def announceSourceFinished(self, srcString):
		self.popIndent()
		self.showMsg("Done %s, read %d"%(srcString, self.dispatcher.totalRead))
	
	@base.listensTo("SourceError")
	def announceSourceError(self, srcString):
		self.popIndent()
		self.showMsg("Failed %s"%srcString)

	@base.listensTo("Shipout")
	def announceShipout(self, noShipped):
		self.showMsg("Shipped %d/%d"%(
			noShipped, self.dispatcher.totalShippedOut))
	
	@base.listensTo("IndexCreation")
	def announceIndexing(self, indexName):
		self.showMsg("Create index %s"%indexName)
	
	@base.listensTo("ScriptRunning")
	def announceScriptRunning(self, arg):
		script, source = arg
		fromNote = ""
		if source:
			fromNote = " on %s"%(getattr(source, "id", None) or repr(source))
		self.showMsg("%s executing script %s%s"%(
			script.__class__.__name__, script.name, fromNote))
	
	@base.listensTo("Info")
	def printInfo(self, message):
		self.showMsg(message)
	
	@base.listensTo("ProcessStarts")
	def openProcess(self, procId):
		sys.stderr.write(f"{self.curIndent}{procId}... ")
		sys.stderr.flush()
		self.clearer = ""
	
	@base.listensTo("Progress")
	def reportProgress(self, nextMessage):
		sys.stderr.write(self.clearer+nextMessage)
		sys.stderr.flush()
		nChar = len(nextMessage)
		self.clearer = ("\b"*nChar+" "*nChar+"\b"*nChar)
	
	@base.listensTo("ProcessEnded")
	def closeProcess(self, procId):
		sys.stderr.write(f"{self.clearer}Done.\n")
