"""
Classes for rendering SVG elements.
"""
from qp.fill.html import element

attribute_mapping = dict(
    xml_space='xml:space',
    xmlns_xlink='xmlns:xlink',
    stroke_width='stroke-width',
    font_size='font-size',
    font_weight='font-weight',
    text_anchor='text-anchor',
    enable_background='enable-background',
    xlink_href='xlink:href',
    view_box='viewBox')


class SVGElement (object):

    default_attributes = dict()

    def __init__(self, *args, **attributes):
        self.content = list(args)
        self.attributes = self.default_attributes.copy()
        self.attributes.update(attributes)

    def add_attributes(self, **attributes):
        self.attributes.update(attributes)

    def set_transform(self, *args):
        self.add_attributes(transform=" ".join(str(a) for a in args))

    def add(self, *args):
        for arg in args:
            self.content.append(arg)

    def get_content(self):
        return self.content

    def get_attributes(self, **attributes):
        result = dict()
        attrs = self.attributes.copy()
        attrs.update(attributes)
        for key, value in attrs.items():
            result[attribute_mapping.get(key, key)] = value
        return result

    def render_content(self):
        result = []
        for item in self.content:
            if isinstance(item, SVGElement):
                result.append(item.render())
            else:
                result.append(item)
        return result

    def render_element_name(self):
        return getattr(self, 'element_name',  self.__class__.__name__.lower())

    def render(self, **attributes):
        return element(self.render_element_name(), tuple(self.render_content()), **self.get_attributes(**attributes))


class SVG (SVGElement):

    default_attributes = dict(
            version="1.1",
            xmlns="http://www.w3.org/2000/svg",
            xmlns_xlink="http://www.w3.org/1999/xlink",
            xml_space="preserve")

class Text (SVGElement):

    default_attributes = dict(
        fill="#000",
        stroke="none")

class TextPath (SVGElement): pass
class TSpan (SVGElement): pass
class A (SVGElement): pass
class G (SVGElement): pass
class Defs (SVGElement): pass
class Use (SVGElement): pass
class PolyLine (SVGElement): pass
class Polygon (SVGElement): pass
class Circle (SVGElement): pass
class Ellipse (SVGElement): pass
class Rect (SVGElement): pass
class Title (SVGElement): pass
class Desc (SVGElement): pass
class LinearGradient (SVGElement): element_name = 'linearGradient'
class RadialGradient (SVGElement): element_name = 'radialGradient'
class Stop (SVGElement): pass

class Path (SVGElement):

    def __init__(self, *args, **kwargs):
        SVGElement.__init__(self, *args, **kwargs)
        self.data = []

    def add_data(self, *args):
        for arg in args:
            self.data.append(arg)

    def move_to(self, x, y):
        self.add_data('M', x, y)

    def move_to_relative(self, x, y):
        self.add_data('m', x, y)

    def line_to(self, x, y):
        self.add_data('L', x, y)

    def line_to_relative(self, x, y):
        self.add_data('l', x, y)

    def horizontal_line_to(self, x,):
        self.add_data('H', x)

    def horizontal_line_to_relative(self, x):
        self.add_data('h', x)

    def vertical_line_to(self, y):
        self.add_data('V', y)

    def vertical_line_to_relative(self, y):
        self.add_data('v', y)

    def curve_to(self, x1, y1, x2, y2, x, y):
        self.add_data('C', x1, y1, x2, y2, x, y)

    def curve_to_relative(self, x1, y1, x2, y2, x, y):
        self.add_data('c', x1, y1, x2, y2, x, y)

    def smooth_curve_to(self, x2, y2, x, y):
        self.add_data('S', x2, y2, x, y)

    def smooth_curve_to_relative(self, x2, y2, x, y):
        self.add_data('s', x2, y2, x, y)

    def quadratic_bezier_curve_to(self, x1, y1, x, y):
        self.add_data('Q', x1, y1, x, y)

    def quadratic_bezier_curve_to_relative(self, x1, y1, x, y):
        self.add_data('q', x1, y1, x, y)

    def smooth_quadratic_bezier_curve_to(self, x, y):
        self.add_data('T', x, y)

    def smooth_quadratic_bezier_curve_to_relative(self, x, y):
        self.add_data('t', x, y)

    def arc(self, rx, ry, x_axis_rotation, large_arc_flag, sweep_flag, x, y):
        """
        Draws an elliptical arc from the current point to the point x,y. rx and ry are the elliptical radius in x and y direction.
        The x-rotation determines how much the elliptical arc is to be rotated around the x-axis.
        The large_arc_flag, along with the sweep_flag, determine which of the 2 possible arcs to draw.
        The sweep-flag determines the direction to draw the arc in. 0 means end at x, y.
        """
        self.add_data('A', rx, ry, x_axis_rotation, flag(large_arc_flag), flag(sweep_flag), x, y)

    def arc_relative(self, rx, ry, x_axis_rotation, large_arc_flag, sweep_flag, x, y):
        self.add_data('a', rx, ry, x_axis_rotation, flag(large_arc_flag), flag(sweep_flag), x, y)

    def close(self):
        self.add_data('z')

    def render(self, **attributes):
        attributes['d'] = ' '.join(map(str, self.data))
        return SVGElement.render(self, **attributes)


def flag(x):
    if x:
        return 1
    else:
        return 0



