# -*- coding: iso-8859-1 -*-
"""
	MoinMoin - FreeMind Flash Browser macro

	Thin macro based on FreeMind Browser (applet) macro

	Inserts the FreeMind Flash Browser
	See http://freemind.sourceforge.net/wiki/index.php/Flash

	[[FreeMindFlashBrowser( urlOfMindmap )]]
		displays the FreeMind mindmap specified by urlOfMindmap in the FreeMind
		browser applet there is a default for the width, height, and
		collapsedToLevel of the applet.

	[[FreeMindFlashBrowser( urlOfMindmap, width )]]
		displays the FreeMind mindmap specified by urlOfMindmap in the FreeMind
		browser applet the width is taken from the argument list there is a
		default for the height and collapsedToLevel of the applet.

	[[FreeMindFlashBrowser( urlOfMindmap, width, height )]]
		displays the FreeMind mindmap specified by urlOfMindmap in the FreeMind
		browser applet the width and height are taken from the argument list.
		There is a default for the collapsedToLevel of the applet.

	[[FreeMindFlashBrowser( urlOfMindmap, width, height, collapsedToLevel )]]
		displays the FreeMind mindmap specified by urlOfMindmap in the FreeMind
		browser applet the width, height and collapsedToLevel are taken from the
		argument list.

	@copyright: 2007 by Bum-seok Lee <shinsuk@gwbs.net>
	@license: GNU GPL, see COPYING for details.
"""

"""
	Changes:

		2007-12-14 siemster <gregory.siems@pca.state.mn.us>
			- Moved mmcachedir to wikiconfig ( as freemind_cache_dir )
			- Moved mmmcacheurl to wikiconfig ( as freemind_cache_url )
			- Moved flashurl to wikiconfig  ( as freemind_flash_browser_url )
			- Added CSSFile ( freemind_css_url in wikiconfig )
			- Added collapsedToLevel
			- Changed 'div id' of the applet script to a generated value
				(for the purpose of allowing multiple instances within the
				same wiki page)

		2008-06-27 siemster <gregory.siems@pca.state.mn.us>
			- Fix to work with Moin version 1.7

"""

from MoinMoin.action import AttachFile
import os
import md5

debug = False

# FMBMacro class

"""
	Class FMBMacro implements the execution of a FreeMindFlashBrowser macro call.
	One instance must be used per execution.
"""
class FMBMacro:

	widthDefault = '100%'
	heightDefault= '500'
	collapsedLevelDefault = '2'

	"""
		Construct the FMBMacro with the execution arguments.
	"""
	def __init__(self, macro, args):
		self.macro = macro
		self.args = args

		self.flashBaseUrl  = macro.request.cfg.freemind_flash_browser_url
		self.cssUrl        = macro.request.cfg.freemind_css_url
		self.mmCacheUrl    = macro.request.cfg.freemind_cache_url
		self.mmCacheDir    = macro.request.cfg.freemind_cache_dir

		# Check and set, if we have an HTML formatter
		self.isHTML = '<br />\n' == self.macro.formatter.linebreak(0)

		# Fix for Moin 1.7.x
		if not self.isHTML:
			self.isHTML = '<br>\n' == self.macro.formatter.linebreak(0)

		self.isFatal = False
		self.applet = [] # this is for the applet code
		self.messages = [] # this is for extra messages


	def execute( self ):
		self.info( "Yippieh - FMBMacro is executing!" )
		self.checkArguments()
		self.computeResult()
		return self.result


	"""
		Check the arguments given with the macro call.
	"""
	def checkArguments(self):

		if not self.args:
			self.fatal( "At least one argument, i.e. the URL for the mindmap is expected!" )
			self.usage()
		else:
			argsList = self.args.split(',')
			argsLen = len(argsList)

		self.width = FMBMacro.widthDefault
		self.height = FMBMacro.heightDefault
		self.collapsedLevel = FMBMacro.collapsedLevelDefault

		mindmap = argsList[0].strip()

		if 2 <= argsLen:
			temp = argsList[1].strip()
			if temp != '':
				self.width = temp

		if 3 <= argsLen:
			temp = argsList[2].strip()
			if temp != '':
				self.height = temp

		if 4 <= argsLen:
			temp = argsList[3].strip()
			if temp != '':
				self.collapsedLevel = temp

		if 4 < argsLen:
			self.warning( "Too many arguments!" )
			self.usage()

		self.mindmapUrl = self.getMindmapURL(mindmap)

		if True:
			self.info( "isHTML= '%s'" %(self.isHTML) )
			self.info( "mindmap= '%s'" %(mindmap) )
			self.info( "width= '%s'" %(self.width) )
			self.info( "height= '%s'" %(self.height) )
			self.info( "startCollapsedToLevel= '%s'" %(self.collapsedLevel) )
			self.info( "mindmap-url= '%s'" %(self.mindmapUrl) )
			self.info( "isFatal= '%s'" %(self.isFatal) )
			self.usage()

	"""
		Compute the result of the macro call.
	"""
	def computeResult(self):
		result = "".join( self.messages )

		if not self.isFatal:
			self.computeApplet()
			result += "".join( self.applet )

		if self.isHTML:
			self.result = self.macro.formatter.rawHTML( result )
		else:
			self.result = result


	"""
		Compute the applet link or applet tag (depending on formatter)
	"""
	def computeApplet( self ):
		if self.isHTML:
			divId = md5.new(self.mindmapUrl).hexdigest()

			applet = """
<!--
 - code generated by FreeMindFlashBrowser flash macro -
 - see http://freemind.sourceforge.net -
-->
<script type="text/javascript" src="%s/flashobject.js"></script>

<div id="%s">
	Flash plugin or Javascript are turned off.
	Activate both and reload to view the mindmap
</div>

<script type="text/javascript">
	// <![CDATA[
	var fo = new FlashObject("%s/visorFreemind.swf", "visorFreeMind", "%s", "%s", 6, "#9999ff");
	fo.addVariable("openUrl", "_self");
	fo.addVariable("initLoadFile", "%s");
	fo.addVariable("startCollapsedToLevel", "%s");
	fo.addVariable("CSSFile", "%s");
	fo.write("%s");
	// ]]>
</script>
""" %( self.flashBaseUrl, divId, self.flashBaseUrl, self.width, self.height,
			self.mindmapUrl, self.collapsedLevel, self.cssUrl, divId, )
			self.applet.append( applet )

		else:
			self.applet.append( self.macro.formatter.url( 1, self.mindmapUrl ) )
			self.applet.append( self.macro.formatter.url( 0 ) )


	# message methods

	def info( self, msg ):
		if debug:
		    self.msg( 'Info: ' + msg )

	def warning( self, msg ):
		self.msg( 'Warning: ' + msg )

	def error( self, msg ):
		self.msg( 'Error: ' + msg )

	def fatal( self, msg ):
		self.msg( 'Fatal: ' + msg )
		self.isFatal = True

	def msg( self, msg ):
		msg = "FreeMindFlashBrowser-Macro:" + msg
		print msg
		if self.isHTML:
			msg = '<h1 style="font-weight:bold;color:blue">' + msg.replace( '\n', '\n<br/>') + '</h1>'

		self.messages.append(msg)


	def usage( self ):
		usage = """
		Usage: [[FreeMindFlashBrowser( urlOfMindmap [,width [,height]] )]]
			urlOfMindmap: an URL reaching the mindmap - allowed schemes are 'http:' and 'attachment:'.
			width:		      (optional) - width of the applet; default: %s
			height:		      (optional) - height of the applet; default: %s
			startCollapsedToLevel (optional) - start collapsed to to node level; default: %s
		""" %(self.widthDefault, self.heightDefault, self.collapsedLevelDefault)

		self.info( usage )


	"""
		Take the given URL of the mindmap, validate it and return an URL that can be linked to from the applet.
	"""
	def getMindmapURL( self, url ):

		if url.startswith( 'http:' ):
			return url

		elif url.startswith( 'attachment:'):
			mmFileName = url[11:]
			wikiPageName = self.macro.formatter.page.page_name
			attachDir    = os.path.abspath(AttachFile.getAttachDir ( self.macro.request, wikiPageName ))
			wikiDir      = os.getcwd().split('/')[-1]

			# As there may be multiple wikis on the same server,
			# ensure that each wiki has it's own subdir under the mm cache dir
			dirName = os.path.join ( self.mmCacheDir, wikiDir )
			if not os.path.isdir(dirName):
				os.mkdir(dirName, 0755)

			# Deal with slashes '/' in the wiki page name
			for token in wikiPageName.split('/'):
				dirName = os.path.join(dirName, token)
				if not os.path.isdir(dirName):
					os.mkdir(dirName, 0755)

			cacheDir = os.path.join ( self.mmCacheDir, wikiDir, wikiPageName, 'attachments' )

			try: os.symlink ( attachDir, cacheDir )
			except OSError, e:
				if e.errno == 17: pass
				else: raise

			return_url = os.path.join ( self.mmCacheUrl, wikiDir, wikiPageName, 'attachments', mmFileName )
			return return_url

		else:
			self.warning( "Unrecognized scheme in mindmap URL! Url is '%s'!" %(url) )
			self.usage()
			return url


# Macro execution interface

def execute(macro, args):

	fmb = FMBMacro( macro, args )
	return fmb.execute()

# vim: ai si cin noet ts=4 sw=4

