
from random import choice
from traits.api import Any, Enum, HasTraits, Instance, Int, List, Str
from chaco.example_support import COLOR_PALETTE
from chaco.api import Plot
from chaco.plot_canvas_toolbar import PlotToolbarButton

DEBUG = False

class ButtonController(HasTraits):
    """ Tells buttons what to do

    Buttons defer to this when they are activated.
    """

    modifier = Enum("control", "shift", "alt")

    # The list of buttons that are currently "down"
    active_buttons = List

    # A reference to the Plot object that displays scatterplots of multiple
    # dataseries
    plot = Instance(Plot)

    # The transient plot overlay housing self.plot
    plot_overlay = Any

    # The name of the scatter plot in the Plot
    _scatterplot_name = "ButtonControllerPlot"

    def notify(self, button, type, event):
        """ Informs the controller that the particular **button** just
        got an event.  **Type** is either "up" or "down".  Event is the
        actual mouse event.
        """
        #control_down = getattr(event, self.modifier + "_down", False)
        control_down = True
        if DEBUG:
            print "[notify]", button.plotname, type, "control:", control_down
        if type == "down":
            if control_down and button in self.active_buttons:
                self.button_deselected(button)
            else:
                if not control_down:
                    # Deselect all current buttons and select the new one
                    [self.button_deselected(b) for b in self.active_buttons \
                            if b is not button]
                self.button_selected(button)
        else:  # type == "up"
            #if not control_down:
            if 1:
                self.button_deselected(button)
        return

    def button_selected(self, button):
        if DEBUG:
            print "active:", [b.plotname for b in self.active_buttons]
            print "new button selected:", button.plotname
        if button in self.active_buttons:
            return
        numbuttons = len(self.active_buttons)
        if numbuttons == 0:
            self.active_buttons.append(button)
            button.show_overlay()
        elif numbuttons == 1:
            self.active_buttons[0].hide_overlay()
            self.active_buttons.append(button)
            self.show_scatterplot(*self.active_buttons)
        elif numbuttons == 2:
            # Replace the last active button with the new one
            self.active_buttons[1].button_state = "up"
            self.active_buttons[1] = button
            self.hide_scatterplot()
            self.show_scatterplot(*self.active_buttons)
        else:
            return
        button.button_state = "down"
        return

    def button_deselected(self, button):
        if DEBUG:
            print "active:", [b.plotname for b in self.active_buttons]
            print "new button deselected:", button.plotname
        if button not in self.active_buttons:
            button.button_state = "up"
            return
        numbuttons = len(self.active_buttons)
        if numbuttons == 1:
            if button in self.active_buttons:
                self.active_buttons.remove(button)
            button.hide_overlay()
        elif numbuttons == 2:
            if button in self.active_buttons:
                self.active_buttons.remove(button)
                self.hide_scatterplot()
                remaining_button = self.active_buttons[0]
                remaining_button.show_overlay()
        else:
            return
        button.button_state = "up"
        return

    def show_scatterplot(self, b1, b2):
        if len(self.plot.plots) > 0:
            self.plot.delplot(*self.plot.plots.keys())

        cur_plot = self.plot.plot((b1.plotname+"_y", b2.plotname+"_y"),
                                  name=self._scatterplot_name,
                                  type="scatter",
                                  marker="square",
                                  color=tuple(choice(COLOR_PALETTE)),
                                  marker_size=8,
                                  )
        self.plot.index_axis.title = b1.plotname
        #self.plot.value_axis.title = b2.plotname
        self.plot.title = b1.plotname + " vs. " + b2.plotname
        self.plot_overlay.visible = True
        self.plot.request_redraw()

    def hide_scatterplot(self):
        if self._scatterplot_name in self.plot.plots:
            self.plot.delplot(self._scatterplot_name)
            self.plot.index_range.set_bounds("auto", "auto")
            self.plot.value_range.set_bounds("auto", "auto")
        self.plot_overlay.visible = False



class DataSourceButton(PlotToolbarButton):

    # A TransientPlotOverlay containing the timeseries plot of this datasource
    plot_overlay = Any

    plotname = Str

    canvas = Any

    #overlay_bounds = List()

    # Can't call this "controller" because it conflicts with old tool dispatch
    button_controller = Instance(ButtonController)

    # Override inherited trait
    label_color = (0,0,0,1)

    resizable = ""

    cur_bid = Int(-1)

    # The overlay to display when the user holds the mouse down over us.
    #_overlay = Instance(AbstractOverlay)

    def normal_left_down(self, event):
        self.button_state = "down"
        self.button_controller.notify(self, "down", event)
        event.handled = True
        self.request_redraw()

    def normal_left_up(self, event):
        self.button_state = "up"
        self.button_controller.notify(self, "up", event)
        event.handled = True
        self.request_redraw()

    def normal_blob_down(self, event):
        if self.cur_bid == -1:
            self.cur_bid = event.bid
            self.normal_left_down(event)
            if hasattr(event, "bid"):
                event.window.capture_blob(self, event.bid,
                                          event.net_transform())

    def normal_blob_up(self, event):
        if event.bid == self.cur_bid:
            if hasattr(event, "bid"):
                event.window.release_blob(event.bid)
            self.cur_bid = -1
            self.normal_left_up(event)

    def normal_mouse_leave(self, event):
        if event.left_down:
            return self.normal_left_up(event)

    def normal_mouse_enter(self, event):
        if event.left_down:
            return self.normal_left_down(event)

    def show_overlay(self):
        if self.plot_overlay is not None:
            self._do_layout()
            self.plot_overlay.visible = True
        self.request_redraw()
        return

    def hide_overlay(self):
        if self.plot_overlay is not None:
            self.plot_overlay.visible = False
        self.request_redraw()
        return

    def _do_layout(self):
        if self.canvas is not None:
            boff = self.canvas.bounds_offset
            self.plot_overlay.offset = (boff[0],
                    boff[1] + self.y - self.container.y + self.height/2)
        self.plot_overlay.do_layout()
