
from docutils import nodes, utils
from docutils.parsers.rst import directives
from sphinx.util.compat import Directive


DEFAULT_PLACES  = 'btp'
DEFAULT_PADDING = '0.1'


# subflt
############################################################################

class subcap(nodes.Part, nodes.TextElement):
    pass

def latex_visit_subcap(self, node):
    self.body.append('[')

def latex_depart_subcap(self, node):
    self.body.append(']{')


class subflt(nodes.General, nodes.Element):
    pass

def latex_visit_subflt(self, node):
    space = '\\hspace{%sin}\n' % node['space'] if node['space'] else ''
    self.body.append(space)
    self.body.append('\\subfloat')

def latex_depart_subflt(self, node):
    self.body.append('}\n')


class SubfltDirective(Directive):

    has_content = True
    required_arguments = 0
    optional_arguments = 1
    final_argument_whitespace = True
    option_spec = dict(
        label   = directives.unchanged,
        space   = float,
    )

    def run(self):
        self.assert_has_content()
        subflt_node = subflt('\n'.join(self.content))
        subflt_node['label'] = self.options.get('label', None)
        subflt_node['space'] = self.options.get('space', None)
        if self.arguments and self.arguments[0]:
            subflt_node['label'] = self.arguments[0]
        node = nodes.Element() # anonymous container for parsing
        self.state.nested_parse(self.content, self.content_offset, node)
        first_node = node[0]
        if isinstance(first_node, nodes.paragraph):
            cap = subcap(first_node.rawsource, '', *first_node.children)
            subflt_node += cap
            subflt_node += node[1:]
        else:
            subflt_node += subcap('', '', nodes.Text(''))
            subflt_node += node[:]
        return [subflt_node]


# captions / padding
############################################################################

class captitle(nodes.Part, nodes.TextElement):
    pass

def latex_visit_captitle(self, node):
    self.body.append('\\caption[')

def latex_depart_captitle(self, node):
    self.body.append(']')

class capdesc(nodes.Part, nodes.TextElement):
    pass

def latex_visit_capdesc(self, node):
    self.body.append('{')

def latex_depart_capdesc(self, node):
    self.body.append('}\n')

class pad(nodes.Part, nodes.TextElement):
    pass

def latex_visit_pad(self, node):
    self.body.append('\\hspace{%sin}\n' % node['inches'])

def latex_depart_pad(self, node):
    pass
    #self.body.append('\\hspace{%sin}\n' % DEFAULT_PADDING) #node['inches'])



# flt
############################################################################

class flt(nodes.General, nodes.Element):
    pass

def latex_visit_flt(self, node):
    self.body.append('\\begin{%s}[%s]\n' % (node['type'], node['placement']))
    self.body.append('' if node['nocenter'] else '\\centering\n')

def latex_depart_flt(self, node):
    label = '\\label{%s}\n' % node['label'] if node['label'] else ''
    self.body.append(label)
    self.body.append('\\end{%s}\n\n' % node['type'])

class FltDirective(Directive):

    flt_types = ('figure', 'table')
    def flt_type(argument):
        # This is not callable as self.align.  We cannot make it a
        # staticmethod because we're saving an unbound method in
        # option_spec below.
        return directives.choice(argument, FltDirective.flt_types)

    has_content = True
    required_arguments = 0
    optional_arguments = 1
    final_argument_whitespace = True
    option_spec = dict(
        type      = flt_type,
        label     = directives.unchanged,
        placement = directives.unchanged,
        padding   = float,
        nocenter  = directives.flag,
    )

    def run(self):
        self.assert_has_content()
        flt_node = flt('\n'.join(self.content))
        flt_node['type'] = self.options.get('type', 'figure')
        flt_node['label'] = self.options.get('label', None)
        flt_node['placement'] = self.options.get('placement', DEFAULT_PLACES)
        flt_node['padding'] = self.options.get('padding', DEFAULT_PADDING)
        flt_node['nocenter'] = 'nocenter' in self.options
        if self.arguments and self.arguments[0]:
            flt_node['label'] = self.arguments[0]
        node = nodes.Element() # anonymous container for parsing
        self.state.nested_parse(self.content, self.content_offset, node)
        first_node = None
        second_node = None
        try:
            first_node = node[0]
            second_node = node[1]
        except IndexError:
            pass
        is_first_para = isinstance(first_node, nodes.paragraph)
        is_second_para = isinstance(second_node, nodes.paragraph)
        capt = None
        capd = None
        if is_first_para and is_second_para:
            capt = captitle(first_node.rawsource, '', *first_node.children)
            capd = capdesc(second_node.rawsource, '', *second_node.children)
            node = node[2:]
        elif is_first_para:
            capt = captitle(first_node.rawsource, '', *first_node.children)
            capd = capdesc(first_node.rawsource+'.', '',
                    *(first_node.children + [nodes.Text('.')]))
            node = node[1:]
        elif is_second_para:
            capt = captitle(second_node.rawsource, '', *second_node.children)
            capd = capdesc(second_node.rawsource+'.', '',
                    *(second_node.children + [nodes.Text('.')]))
            node = node[1:]
        first = True
        children = []
        for n in node:
            if isinstance(n, subflt):
                if first:
                    first = False
                else:
                    children.append(pad('', '', nodes.Text(''),
                            inches=flt_node['padding']))
            children.append(n)
        flt_node += children
        if capt and capd:
            flt_node += capt
            flt_node += capd
        return [flt_node]



def setup(app):
    app.add_node(subcap, latex=(latex_visit_subcap, latex_depart_subcap))
    app.add_node(subflt, latex=(latex_visit_subflt, latex_depart_subflt))
    app.add_node(captitle, latex=(latex_visit_captitle, latex_depart_captitle))
    app.add_node(capdesc, latex=(latex_visit_capdesc, latex_depart_capdesc))
    app.add_node(pad, latex=(latex_visit_pad, latex_depart_pad))
    app.add_node(flt, latex=(latex_visit_flt, latex_depart_flt))
    app.add_directive('flt', FltDirective)
    app.add_directive('subflt', SubfltDirective)


# vim: set et sw=4 sts=4 :
