text: # -*- coding: utf-8 -*-
  
  import re
  import six
  from .utils import tag_test
  
  class Node(object):
  
      def __init__(self):
          self._children = []
          self._root = None
          self.parent = None
          self.no = None
  
      @property
      def root(self):
          if self._root is None:
              self._root = self.parent.root
          return self._root
  
      def append(self, child):
          self._children.append(child)
  
      def add_child(self, child):
          child.no = len(self._children)
          child.parent = self
          self.append(child)
  
      def children_to_tag(self):
          x = []
          for child in self._children:
              x.append(child.to_tag())
          return ''.join(x)
  
      def to_tag(self):
          self.root.node_map[self.tpl_key] = self
          return self.tag_tpl % (self.tpl_key, self.children_to_tag())
  
      def process_xv(self, xv):
          self.xv = xv
          return six.text_type(xv)
  
  class Row(Node):
      tag_tpl = "{%% row '%s' %%}\n%s"#{%% endrow %%}
      html_tpl = '</tr><tr>\n'
  
      def __init__(self, rowx):
          Node.__init__(self)
          self.rowx = rowx
  
      @property
      def tpl_key(self):
          return str(self.rowx)
  
      def process_rv(self, rv, sheet_pos):
          wtrowx = sheet_pos.next_row()
          sheet_pos.wtsheet.row(self.rowx, wtrowx)
          return self.to_html()
  
      def to_html(self):
          return self.html_tpl
  
  class Cell(Node):
      tag_tpl = "{%% cell '%s' %%}%s{%% endcell %%}\n"
      html_tpl = '<td>%s</td>\n'
  
      def __init__(self, rowx, colx, value, cty):
          Node.__init__(self)
          self.rowx = rowx
          self.colx = colx
          self.value = value
          self.cty = cty
  
      @property
      def tpl_key(self):
          return '%d,%d' % (self.rowx, self.colx)
  
      def process_rv(self, rv, sheet_pos):
          self.write(self.value, self.cty, sheet_pos)
          return self.to_html()
  
      def write(self, value, cty, sheet_pos):
          wtrowx, wtcolx = sheet_pos.next_cell()
          sheet_pos.wtsheet.cell(self.rowx, self.colx, wtrowx, wtcolx, value, cty)
  
      def to_html(self):
          if self.value is None:
              value = ''
          else:
              value = self.value
          return self.html_tpl % six.text_type(value)
  
  class EmptyCell(Cell):
  
      def __init__(self, rowx, colx):
          Cell.__init__(self, rowx, colx, None, None)
  
      def process_rv(self, rv, sheet_pos):
          sheet_pos.next_cell()
          return self.to_html()
  
  class RichCell(Cell):
  
      def __init__(self, rowx, colx, value, cty, rich_text):
          Cell.__init__(self, rowx, colx, value, cty)
          self.rich_text = rich_text
  
      def process_rv(self, rv, sheet_pos):
          self.write(self.rich_text, self.cty, sheet_pos)
          return self.to_html()
  
      def to_html(self):
          return self.html_tpl % self.value
  
  
  class VMap():
  
      def __init__(self, font):
          self.font = font
          self.kvs = {}
          self.section_keys = []
  
      def addv(self, value):
          if isinstance(value, six.text_type):
              return value
          key = "__%d__" % len(self.kvs)
          self.kvs[key] = value
          return key
  
      def add_section(self, section):
          key = self.addv(section)
          self.section_keys.append(key)
          s = Section(section, key)
          self.add_child(s)
  
      def add_tag_section(self, text, font):
          s = TagSection(text, font, 1)
          self.add_child(s)
  
      def pack(self, text):
          if len(self.kvs) == 0:
              return text
          pattern = '(__\d*__)'
          p = re.compile(pattern)
          parts = p.split(text)
          rv = []
          for index, part in enumerate(parts):
              if index % 2 == 0:
                  if part:
                      v = self.root.rich_handler.rich_segment(part, self.font)
                      rv.append(v)
              else:
                  value = self.kvs[part]
                  if isinstance(value, list):
                      rv.extend(value)
                  else:
                      rv.append(value)
          self.reset()
          return rv
  
      def reset(self):
          if len(self.section_keys) == 0:
              self.kvs.clear()
              return
          for k in list(self.kvs.keys()):
              if k not in self.section_keys:
                  del self.kvs[k]
  
      def unpack(self, rich_text):
          section = []
          for text,font,segment in self.root.rich_handler.iter(rich_text, self.font):
              if tag_test(text):
                  if section:
                      self.add_section(section)
                      section = []
                  self.add_tag_section(text, font)
              else:
                  section.append(segment)
          if section:
              self.add_section(section)
  
  class Section():
  
      def __init__(self, section, key):
          self.section = section
          self.key = key
  
      def to_tag(self):
          return self.key
  
  
  class TagSection(VMap, Node):
      tag_tpl = "{%% sec '%s' %%}%s{%% endsec %%}"
  
      def __init__(self, text, font, level=0):
          Node.__init__(self)
          VMap.__init__(self, font)
          self.text = text
          self.level = level
  
      @property
      def tpl_key(self):
          return '%s,%d' % (self.parent.tpl_key, self.no)
  
      def to_tag(self):
          self.root.node_map[self.tpl_key] = self
          return self.tag_tpl % (self.tpl_key, self.text)
  
      def process_rv(self, rv, sheet_pos):
          rv = self.pack(rv)
          if isinstance(rv, six.text_type) and self.level > 0:
              rv = self.root.rich_handler.rich_segment(rv, self.font)
          if not isinstance(rv, six.text_type):
              rv = self.parent.addv(rv)
          return rv
  
  class TagCell(Cell):
  
      def __init__(self, rowx, colx, value, cty, font):
          Cell.__init__(self, rowx, colx, value, cty)
          self.font = font
          self.rv = None
  
      def addv(self, rv):
          self.rv = rv
          return ''
  
      def process_rv(self, rv, sheet_pos):
          if self.rv:
              rv = self.root.rich_handler.rich_content(self.rv)
              self.rv = None
          self.write(rv, self.cty, sheet_pos)
          return self.to_html(rv)
  
      def to_tag(self):
          tag_section = TagSection(self.value, self.font)
          self.add_child(tag_section)
          return Cell.to_tag(self)
  
      def to_html(self, value=None):
          if not value:
              return self.html_tpl % six.text_type(self.value)
          else:
              return self.html_tpl % self.root.rich_handler.text_content(value)
  
  class XvCell(Cell):
  
      def __init__(self, rowx, colx, value, cty):
          Cell.__init__(self, rowx, colx, value, cty)
          self.xv = None
  
      def process_rv(self, rv, sheet_pos):
          if self.xv:
              self.write(self.xv, None, sheet_pos)
          else:
              self.write(rv, None, sheet_pos)
          return self.to_html(rv)
  
      def to_tag(self):
          self.root.node_map[self.tpl_key] = self
          return self.tag_tpl % (self.tpl_key, self.value)
  
      def to_html(self, value=None):
          return self.html_tpl % value
  
  class RichText(VMap):
  
      def __init__(self, rich_text, font):
          VMap.__init__(self, font)
          self.rich_text = rich_text
  
  
  class RichTagCell(Cell, RichText):
  
      def __init__(self, rowx, colx, value, cty, rich_text, font):
          Cell.__init__(self, rowx, colx, value, cty)
          RichText.__init__(self, rich_text, font)
  
      def process_rv(self, rv, sheet_pos):
          rv = self.pack(rv)
          rv = self.root.rich_handler.rich_content(rv)
          self.write(rv, self.cty, sheet_pos)
          return self.to_html(rv)
  
      def to_tag(self):
          self.unpack(self.rich_text)
          return Cell.to_tag(self)
  
      def to_html(self, value=None):
          if not value:
              value = self.rich_text
          return self.html_tpl % self.root.rich_handler.text_content(value)
  
  
  class SheetNodes(Node):
  
      def __init__(self):
          Node.__init__(self)
          self.node_map = {}
          self._root = self
  
      def to_tag(self):
          return self.children_to_tag()
  
  
  
  class SheetPos():
  
      def __init__(self, wtsheet, sheet_nodes, first_row, first_col):
          self.wtsheet = wtsheet
          self.sheet_nodes = sheet_nodes
          self.first_row = first_row - 1
          self.first_col = first_col - 1
          self.rowx = self.first_row
          self.colx = self.first_col
  
      def next_cell(self):
          self.colx += 1
          return self.rowx, self.colx
  
      def next_row(self):
          self.rowx += 1
          self.colx = self.first_col
          return self.rowx
  
      def coords(self):
          return self.rowx, self.colx
  
      def get_node(self, key):
          self.current_node = self.sheet_nodes.node_map.get(key)
          return self.current_node