# Wrapper classes for gdchart library
# written by NAS, 2002/02/20
import gdchart
from cStringIO import StringIO

# Save the default option values in a module-level dictionary.  This way, each
# new instance of the Chart class can begin life with its own copy of the
# default option values.
gdchart.defaults = gdchart.option()


def unzip(args):
    """
    inverse of zip. Given: ((1,"a"),(2,"b")) --> ((1,2),("a","b"))
    """
    result = []
    n = min(map(len,args))
    for i in range(n):
        result.append([])
    for i in range(len(args)):
        for j in range(n):
            result[j].append(args[i][j])
    return tuple(result)


# This class is just a container for option values.
class Chart:

    STYLE = None # subclass must override

    DEFAULT_COLORS = (0x6666ff, 0xee0033, 0x00ff66, 0xff6633,
                      0x66ccff, 0xffcc99)

    def __init__(self):
        # Get a copy of the default options
        self.options = gdchart.defaults.copy()
        self.option(bg_color=0xffffff, bg_transparent=1)
        self.set_default_options()

    def set_default_options(self):
        pass

    def option(self, **args):
        # Save option values in the object's dictionary.
        self.options.update(args)

    def transform_data (self, data):
        """Convert data from a friendly form into something gdchart wants"""
        # Convert data:
        #   [("Jan", 52, 23), ("Feb", 59, 34)]
        # to:
        #   [["Jan", "Feb"], [52, 59], [23,  34]]
        return unzip(data)

    def draw(self, file, data, size=(400, 400), **options):
        self.options.update(options)
        gdchart.option(**self.options)
        data = self.transform_data(data)
        labels = data[0]
        data = tuple(data[1:])
        args = (self.STYLE, size, file, labels) + data
        gdchart.chart(*args)

    def draws(self, data, *args, **kwargs):
        out = StringIO()
        self.draw(out, data, *args, **kwargs)
        return out.getvalue()

for name, value in vars(gdchart).items():
    if name.startswith("GDC"):
        setattr(Chart, name, value)


class Pie3DChart(Chart):

    STYLE = Chart.GDC_3DPIE

    def set_default_options(self):
        self.option(pie_color=(0xff0033, 0x6666ff, 0x00ff66, 0xff6633,
                               0x66ccff, 0xffcc99))
        self.option(edge_color=0x0, line_color=0x0)
        self.option(label_font=self.GDC_LARGE)
        self.option(percent_labels=self.GDCPIE_PCT_BELOW)
        self.option(label_dist=17)


class BarChart(Chart):

    STYLE = Chart.GDC_BAR
    
    def set_default_options(self):
        self.option(set_color=self.DEFAULT_COLORS)


class Bar3DChart(BarChart):

    STYLE = Chart.GDC_3DBAR


class LineChart(BarChart):

    STYLE = Chart.GDC_LINE


class FloatingBarChart(BarChart):

    STYLE = gdchart.GDC_FLOATINGBAR

    def transform_data(self, data):
        # Convert data:
        #   data=[("Jan", (23, 52)), ("Feb", (34, 59))]
        # to:
        #   labels=["Jan", "Feb"]; data=([23, 34], [34,  59])
        # XXX only works for one series
        data = list(unzip(data))
        data[1] = unzip(data[1])
        return data
