
# Copyright 2012,2013 Jaap Karssenberg <jaap.karssenberg@gmail.com>

'''This module handles dumping markdown text with pandoc extensions'''

# OPEN ISSUES
# - how to deal with indented paragraphs ?
#   in pandoc indent is verbatim, so now all indent is dropped
# - how to deal with image re-size ?
# - how to deal with tags / anchors ?
# - check does zim always produce a blank line before a heading ?
# - add \ before line ends to match line breaks from user

import re
from zim.parse.encode import escape_string

from zim.formats import *
from zim.parse.links import old_url_link_re
from zim.formats.plain import Dumper as TextDumper


info = {
	'name': 'markdown',
	'desc': 'Markdown Text (pandoc)',
	'mimetype': 'text/markdown',
	'extension': 'md', # Most common extention used on github.
	'native': False,
	'import': False,
	'export': True,
	'usebase': True,
}



class Dumper(TextDumper):
	# Inherit from wiki format Dumper class, only overload things that
	# are different

	BULLETS = {
		UNCHECKED_BOX: '* \u2610',
		XCHECKED_BOX: '* \u2612',
		CHECKED_BOX: '* \u2611',
		MIGRATED_BOX: '* \u25B7',
		TRANSMIGRATED_BOX: '* \u25C1',
		BULLET: '*',
	}

	TAGS = {
		EMPHASIS: ('*', '*'),
		STRONG: ('**', '**'),
		MARK: ('__', '__'), # OPEN ISSUE: not available in pandoc
		STRIKE: ('~~', '~~'),
		VERBATIM: ("``", "``"),
		TAG: ('', ''), # No additional annotation (apart from the visible @)
		SUBSCRIPT: ('~', '~'),
		SUPERSCRIPT: ('^', '^'),
	}

	def dump(self, tree):
		assert self.linker, 'Markdown dumper needs a linker object'
		return TextDumper.dump(self, tree)

	def dump_indent(self, tag, attrib, strings):
		# Prefix lines with one or more tabs
		if attrib and 'indent' in attrib:
			prefix = '> ' * int(attrib['indent'])
			return self.prefix_lines(prefix, strings)
			# TODO enforces we always end such a block with \n unless partial
		else:
			return strings

	dump_p = dump_indent
	dump_div = dump_indent

	def dump_list(self, tag, attrib, strings):
		# OPEN ISSUE: no indent for lists
		if 'indent' in attrib:
			del attrib['indent']
		strings = TextDumper.dump_list(self, tag, attrib, strings)

		if self.context[-1].tag == LISTITEM:
			# sub-list
			return strings
		else:
			# top level list, wrap in empty lines
			strings.insert(0, '\n')
			strings.append('\n')
			return strings

	dump_ul = dump_list
	dump_ol = dump_list

	def dump_li(self, tag, attrib, strings):
		# Markdown does not support letters as list bullets - convert to number
		assert self.context[-1].tag in (BULLETLIST, NUMBEREDLIST), 'Do not support raw pageview output here'
		if self.context[-1].tag == NUMBEREDLIST \
			and not self.context[-1].attrib.get('_iter'):
				# First item on this level
				iter = self.context[-1].attrib.get('start', '1')
				self.context[-1].attrib['_iter'] = convert_list_iter_letter_to_number(iter)
		return TextDumper.dump_li(self, tag, attrib, strings)

	def dump_pre(self, tag, attrib, strings):
		# OPEN ISSUE: no indent for verbatim blocks
		return self.prefix_lines('\t', strings)

	def dump_anchor(self, tag, attrib, strings=None):
		# Syntax of the pandoc header attributes extension
		return ('{#%s}' % attrib['name'],)

	def dump_link(self, tag, attrib, strings=None):
		assert 'href' in attrib, \
			'BUG: link misses href: %s "%s"' % (attrib, strings)
		href = self.linker.link(attrib['href'])
		text = ''.join(strings) or href
		if href == text and old_url_link_re.match(href):
			return ['<', href, '>']
		else:
			return ['[%s](%s)' % (text, href)]

	def dump_img(self, tag, attrib, strings=None):
		src = self.linker.img(attrib['src'])
		text = attrib.get('alt', '')

		# Handle image dimensions and ids
		# Pandoc support setting dimensions like this:
		# ![Alt text](href){ width=500px height=20px }
		dimensions = filter(lambda i: i[0] in ['width', 'height'], attrib.items())
		properties = ["%s=%spx" % (k, v) for k, v in dimensions]

		if 'id' in attrib:
			properties.append('#' + attrib['id'])

		if len(properties) > 0:
			props = '{ %s }' % (' '.join(properties))
		else:
			props = ''

		# Handle image links by nesting the image inside a link
		if 'href' in attrib:
			href = attrib.get('href')
			return ['[![%s](%s)%s](%s)' % (text, src, props, href)]

		return ['![%s](%s)%s' % (text, src, props)]

	def dump_object_fallback(self, tag, attrib, strings=None):
		# dump object as verbatim block
		return self.prefix_lines('\t', strings)

	def dump_table(self, tag, attrib, strings):
		table = []  # result table
		rows = strings

		aligns, _wraps = TableParser.get_options(attrib)
		maxwidths = TableParser.width2dim(rows)
		headsep = TableParser.headsep(maxwidths, aligns, x='|', y='-')
		rowline = lambda row: TableParser.rowline(row, maxwidths, aligns)

		# print table
		table += [rowline(rows[0])]
		table.append(headsep)
		table += [rowline(row) for row in rows[1:]]
		return [line + "\n" for line in table]

	def dump_td(self, tag, attrib, strings):
		text = ''.join(strings) if strings else ''
		return [escape_string(text.replace('\n', '<br>'), '|')]

	dump_th = dump_td

	def dump_line(self, tag, attrib, strings=None):
		return '\n{}\n'.format('*' * 5)
