# -*- coding: utf-8 -*-

import StringIO
from svg import SVGTree

class SVGTreeRenderer:
    def create_streams(self, names):
        streams = (
            names,
            {}
        )
        for n in streams[0]:
            streams[1][n] = StringIO.StringIO()
        
        return streams

    def render(self, svg_tree):
        pass

class SVGTreeRendererPM(SVGTreeRenderer):
    NODE_DIM = 20.
    PADDING_X = 75.
    PADDING_Y = 75.
    TEXT_SIZE = 15.
    IMG_PADDING = NODE_DIM + 10

    def render(self, svg_tree):
        self.pre_process(svg_tree)
    
        streams = self.create_streams(('style', 'rect', 'path', 'circle', 'text'))
        streams[1]['style'].write(
        '''<style text="text/css">
            circle {
                fill:white;
                stroke:black;
                stroke-width: 2px;
            }
            line {
                stroke:black;
                stroke-width: 1px;
            }
            text {
                font-size: %spx;
                text-anchor: middle;
            }
        </style>''' % self.TEXT_SIZE)
        self.render_(streams[1], 0, 0, None, svg_tree)
        
        dim = (2 * self.IMG_PADDING, 2 * self.IMG_PADDING)
        if svg_tree:
            dim = (dim[0] + svg_tree.width, dim[1] + svg_tree.height)
        return (dim, streams)
        
    def pre_process(self, svg_tree):
        if svg_tree:
            self.pre_process(svg_tree.ls)
            self.pre_process(svg_tree.rs)
            
            svg_tree.width = self.PADDING_X / 2
            svg_tree.height = 0
            
            ls_height = rs_height = 0
            if svg_tree.ls:
                svg_tree.width += svg_tree.ls.width
                ls_height = svg_tree.ls.height
            if svg_tree.rs:
                svg_tree.width += svg_tree.rs.width
                rs_height = svg_tree.rs.height
            if svg_tree.width == 0:
                svg_tree.width = self.PADDING_X
            svg_tree.height = self.PADDING_Y + max(ls_height, rs_height)
        
    def render_(self, streams, x, y, root_cs, svg_tree):
        if svg_tree:
            if svg_tree.ls:
                x_ = x + svg_tree.ls.width
            elif svg_tree.rs:
                x_ = x + self.PADDING_X
            else:
                x_ = x
            cs = (self.IMG_PADDING + x_ + self.PADDING_X / 2, self.IMG_PADDING + y)
            
            streams['circle'].write('<circle cx="%s" cy="%s" r="%s"/>\n' % (
                cs[0], cs[1],
                self.NODE_DIM
            ))
            if svg_tree.key:
                streams['text'].write('<text x="%s" y="%s">%s</text>\n' % (
                    cs[0], cs[1] + self.TEXT_SIZE / 3, svg_tree.key
                ))

            #streams['rect'].write('<rect x="%s" y="%s" width="%s" height="%s" style="fill:#000000; fill-opacity:.1; stroke:black; stroke-width: 1px;"/>' % (
            #   self.IMG_PADDING + x,
            #   self.IMG_PADDING + y, 
            #   svg_tree.width, svg_tree.height
            #))

            if root_cs:
                streams['path'].write('<line x1="%s" y1="%s" x2="%s" y2="%s" />\n' % (root_cs + cs))
                
            y += self.PADDING_Y
            self.render_(streams, x, y, cs, svg_tree.ls)
            self.render_(streams, x_ + self.PADDING_X / 2, y, cs, svg_tree.rs)

class SVGTreeRendererRichard(SVGTreeRenderer):
    NODE_DIM = 20.
    PADDING_X = 5.
    PADDING_Y = 75.
    TEXT_SIZE = 15.
    IMG_PADDING = 5.
    def render(self, svg_tree):
        self.pre_process(svg_tree)
    
        streams = self.create_streams(('style', 'rect', 'path', 'circle', 'text'))
        streams[1]['style'].write(
        '''<style text="text/css">
            circle {
                fill:white;
                stroke:black;
                stroke-width: 2px;
            }
            line {
                stroke:black;
                stroke-width: 1px;
            }
            text {
                font-size: %spx;
                text-anchor: middle;
            }
        </style>''' % self.TEXT_SIZE)
        self.render_(streams[1], 0, 0, None, svg_tree)

        dim = (2 * self.IMG_PADDING, 2 * self.IMG_PADDING)
        if svg_tree:
            dim = (dim[0] + svg_tree.width, dim[1] + svg_tree.height)
        return (dim, streams)

    def pre_process(self, svg_tree):
        if svg_tree:
            prof = self.eval_prof(svg_tree)
            width = 2 * self.NODE_DIM
            prof_ = prof
            while prof_ > 0:
                prof_ -= 1
                width = 2 * width + self.PADDING_X
            
            self.pre_dim(width, prof, svg_tree)
    
    def eval_prof(self, svg_tree):
        if svg_tree:
            return 1 + max(
                self.eval_prof(svg_tree.ls),
                self.eval_prof(svg_tree.rs)
            )
        else:
            return -1
    
    def pre_dim(self, width, prof, svg_tree):
        if svg_tree:
            svg_tree.width = width
            svg_tree.height = 2 * self.NODE_DIM + prof * self.PADDING_Y
            width = (width - self.PADDING_X) / 2
            self.pre_dim(width, prof - 1, svg_tree.ls)
            self.pre_dim(width, prof - 1, svg_tree.rs)
            
    def rien(self):
        if None:
            self.pre_process(svg_tree.ls)
            self.pre_process(svg_tree.rs)
            
            if (svg_tree.ls is not None) & (svg_tree.rs is not None):
                svg_tree.width = self.PADDING_X \
                    + 2 * max(svg_tree.ls.width, svg_tree.rs.width)
                svg_tree.height = 2 * self.NODE_DIM + self.PADDING_Y \
                    + max(svg_tree.ls.height, svg_tree.rs.height)
                    
            elif svg_tree.ls is not None:
                svg_tree.width = self.PADDING_X + 2 * svg_tree.ls.width
                svg_tree.height = 2 * self.NODE_DIM + self.PADDING_Y + svg_tree.ls.height
                
            elif svg_tree.rs is not None:
                svg_tree.width = self.PADDING_X + 2 * svg_tree.rs.width
                svg_tree.height = 2 * self.NODE_DIM + self.PADDING_Y + svg_tree.rs.height
                
            else:
                svg_tree.width = 2 * self.NODE_DIM
                svg_tree.height = 2 * self.NODE_DIM
    
    def render_(self, streams, x, y, root_cs, svg_tree):
        if svg_tree:
            cs = (
                self.IMG_PADDING + x + svg_tree.width / 2,
                self.IMG_PADDING + y + self.NODE_DIM
            )

            if root_cs:
                streams['path'].write('<line x1="%s" y1="%s" x2="%s" y2="%s" />\n' % (root_cs + cs))

            streams['circle'].write('<circle cx="%s" cy="%s" r="%s"/>\n' % (
                cs[0], cs[1],
                self.NODE_DIM
            ))
            if svg_tree.key:
                streams['text'].write('<text x="%s" y="%s">%s</text>\n' % (
                    cs[0], cs[1] + self.TEXT_SIZE / 3, svg_tree.key
                ))

            #streams['rect'].write('<rect x="%s" y="%s" width="%s" height="%s" style="fill:#000000; fill-opacity:.1; stroke:black; stroke-width: 1px;"/>' % (
            #   self.IMG_PADDING + x,
            #   self.IMG_PADDING + y, 
            #   svg_tree.width, svg_tree.height
            #))

            y += self.PADDING_Y
            self.render_(streams, x, y, cs, svg_tree.ls)
            self.render_(streams, x + (svg_tree.width + self.PADDING_X) / 2, y, cs, svg_tree.rs)
            
            
svgtree_renderers = {
    'PM': SVGTreeRendererPM,
    'Richard': SVGTreeRendererRichard,
}