# Copyright (c) 2013 ARM Limited
# All rights reserved
#
# The license below extends only to copyright in the software and shall
# not be construed as granting a license to any other intellectual
# property including but not limited to intellectual property relating
# to a hardware implementation of the functionality of the software
# licensed hereunder.  You may use the software subject to the license
# terms below provided that you ensure that this notice is replicated
# unmodified and in its entirety in all distributions of the software,
# modified or unmodified, in source code or in binary form.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met: redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer;
# redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution;
# neither the name of the copyright holders nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

import pygtk
pygtk.require('2.0')
import gtk
import gobject
import cairo
import re

from .point import Point
from . import parse
from . import colours
from . import model
from .model import Id, BlobModel, BlobDataSelect, special_state_chars
from . import blobs

class BlobView(object):
    """The canvas view of the pipeline"""
    def __init__(self, model):
        # A unit blob will appear at size blobSize inside a space of
        #   size pitch.
        self.blobSize = Point(45.0, 45.0)
        self.pitch = Point(60.0, 60.0)
        self.origin = Point(50.0, 50.0)
        # Some common line definitions to cut down on arbitrary
        #   set_line_widths
        self.thickLineWidth = 10.0
        self.thinLineWidth = 4.0
        self.midLineWidth = 6.0
        # The scale from the units of pitch to device units (nominally
        #   pixels for 1.0 to 1.0
        self.masterScale = Point(1.0,1.0)
        self.model = model
        self.fillColour = colours.emptySlotColour
        self.timeIndex = 0
        self.time = 0
        self.positions = []
        self.controlbar = None
        # The sequence number selector state
        self.dataSelect = BlobDataSelect()
        # Offset of this view's time from self.time used for miniviews
        #   This is actually an offset of the index into the array of times
        #   seen in the event file)
        self.timeOffset = 0
        # Maximum view size for initial window mapping
        self.initialHeight = 600.0

        # Overlays are speech bubbles explaining blob data
        self.overlays = []

        self.da = gtk.DrawingArea()
        def draw(arg1, arg2):
            self.redraw()
        self.da.connect('expose_event', draw)

        # Handy offsets from the blob size
        self.blobIndent = (self.pitch - self.blobSize).scale(0.5)
        self.blobIndentFactor = self.blobIndent / self.pitch

    def add_control_bar(self, controlbar):
        """Add a BlobController to this view"""
        self.controlbar = controlbar

    def draw_to_png(self, filename):
        """Draw the view to a PNG file"""
        surface = cairo.ImageSurface(
            cairo.FORMAT_ARGB32,
            self.da.get_allocation().width,
            self.da.get_allocation().height)
        cr = gtk.gdk.CairoContext(cairo.Context(surface))
        self.draw_to_cr(cr)
        surface.write_to_png(filename)

    def draw_to_cr(self, cr):
        """Draw to a given CairoContext"""
        cr.set_source_color(colours.backgroundColour)
        cr.set_line_width(self.thickLineWidth)
        cr.paint()
        cr.save()
        cr.scale(*self.masterScale.to_pair())
        cr.translate(*self.origin.to_pair())

        positions = [] # {}

        # Draw each blob
        for blob in self.model.blobs:
            blob_event = self.model.find_unit_event_by_time(
                blob.unit, self.time)

            cr.save()
            pos = blob.render(cr, self, blob_event, self.dataSelect,
                self.time)
            cr.restore()
            if pos is not None:
                (centre, size) = pos
                positions.append((blob, centre, size))

        # Draw all the overlays over the top
        for overlay in self.overlays:
            overlay.show(cr)

        cr.restore()

        return positions

    def redraw(self):
        """Redraw the whole view"""
        buffer = cairo.ImageSurface(
            cairo.FORMAT_ARGB32,
            self.da.get_allocation().width,
            self.da.get_allocation().height)

        cr = gtk.gdk.CairoContext(cairo.Context(buffer))
        positions = self.draw_to_cr(cr)

        # Assume that blobs are in order for depth so we want to
        #   hit the frontmost blob first if we search by position
        positions.reverse()
        self.positions = positions

        # Paint the drawn buffer onto the DrawingArea
        dacr = self.da.window.cairo_create()
        dacr.set_source_surface(buffer, 0.0, 0.0)
        dacr.paint()

        buffer.finish()

    def set_time_index(self, time):
        """Set the time index for the view.  A time index is an index into
        the model's times array of seen event times"""
        self.timeIndex = time + self.timeOffset
        if len(self.model.times) != 0:
            if self.timeIndex >= len(self.model.times):
                self.time = self.model.times[len(self.model.times) - 1]
            else:
                self.time = self.model.times[self.timeIndex]
        else:
            self.time = 0

    def get_pic_size(self):
        """Return the size of ASCII-art picture of the pipeline scaled by
        the blob pitch"""
        return (self.origin + self.pitch *
            (self.model.picSize + Point(1.0,1.0)))

    def set_da_size(self):
        """Set the DrawingArea size after scaling"""
        self.da.set_size_request(10 , int(self.initialHeight))

class BlobController(object):
    """The controller bar for the viewer"""
    def __init__(self, model, view,
        defaultEventFile="", defaultPictureFile=""):
        self.model = model
        self.view = view
        self.playTimer = None
        self.filenameEntry = gtk.Entry()
        self.filenameEntry.set_text(defaultEventFile)
        self.pictureEntry = gtk.Entry()
        self.pictureEntry.set_text(defaultPictureFile)
        self.timeEntry = None
        self.defaultEventFile = defaultEventFile
        self.startTime = None
        self.endTime = None

        self.otherViews = []

        def make_bar(elems):
            box = gtk.HBox(homogeneous=False, spacing=2)
            box.set_border_width(2)
            for widget, signal, handler in elems:
                if signal is not None:
                    widget.connect(signal, handler)
                box.pack_start(widget, False, True, 0)
            return box

        self.timeEntry = gtk.Entry()

        t = gtk.ToggleButton('T')
        t.set_active(False)
        s = gtk.ToggleButton('S')
        s.set_active(True)
        p = gtk.ToggleButton('P')
        p.set_active(True)
        l = gtk.ToggleButton('L')
        l.set_active(True)
        f = gtk.ToggleButton('F')
        f.set_active(True)
        e = gtk.ToggleButton('E')
        e.set_active(True)

        # Should really generate this from above
        self.view.dataSelect.ids = set("SPLFE")

        self.bar = gtk.VBox()
        self.bar.set_homogeneous(False)

        row1 = make_bar([
            (gtk.Button('Start'), 'clicked', self.time_start),
            (gtk.Button('End'), 'clicked', self.time_end),
            (gtk.Button('Back'), 'clicked', self.time_back),
            (gtk.Button('Forward'), 'clicked', self.time_forward),
            (gtk.Button('Play'), 'clicked', self.time_play),
            (gtk.Button('Stop'), 'clicked', self.time_stop),
            (self.timeEntry, 'activate', self.time_set),
            (gtk.Label('Visible ids:'), None, None),
            (t, 'clicked', self.toggle_id('T')),
            (gtk.Label('/'), None, None),
            (s, 'clicked', self.toggle_id('S')),
            (gtk.Label('.'), None, None),
            (p, 'clicked', self.toggle_id('P')),
            (gtk.Label('/'), None, None),
            (l, 'clicked', self.toggle_id('L')),
            (gtk.Label('/'), None, None),
            (f, 'clicked', self.toggle_id('F')),
            (gtk.Label('.'), None, None),
            (e, 'clicked', self.toggle_id('E')),
            (self.filenameEntry, 'activate', self.load_events),
            (gtk.Button('Reload'), 'clicked', self.load_events)
            ])

        self.bar.pack_start(row1, False, True, 0)
        self.set_time_index(0)

    def toggle_id(self, id):
        """One of the sequence number selector buttons has been toggled"""
        def toggle(button):
            if button.get_active():
                self.view.dataSelect.ids.add(id)
            else:
                self.view.dataSelect.ids.discard(id)

            # Always leave one thing visible
            if len(self.view.dataSelect.ids) == 0:
                self.view.dataSelect.ids.add(id)
                button.set_active(True)
            self.view.redraw()
        return toggle

    def set_time_index(self, time):
        """Set the time index in the view"""
        self.view.set_time_index(time)

        for view in self.otherViews:
            view.set_time_index(time)
            view.redraw()

        self.timeEntry.set_text(str(self.view.time))

    def time_start(self, button):
        """Start pressed"""
        self.set_time_index(0)
        self.view.redraw()

    def time_end(self, button):
        """End pressed"""
        self.set_time_index(len(self.model.times) - 1)
        self.view.redraw()

    def time_forward(self, button):
        """Step forward pressed"""
        self.set_time_index(min(self.view.timeIndex + 1,
            len(self.model.times) - 1))
        self.view.redraw()
        gtk.gdk.flush()

    def time_back(self, button):
        """Step back pressed"""
        self.set_time_index(max(self.view.timeIndex - 1, 0))
        self.view.redraw()

    def time_set(self, entry):
        """Time dialogue changed.  Need to find a suitable time
        <= the entry's time"""
        newTime = self.model.find_time_index(int(entry.get_text()))
        self.set_time_index(newTime)
        self.view.redraw()

    def time_step(self):
        """Time step while playing"""
        if not self.playTimer \
            or self.view.timeIndex == len(self.model.times) - 1:
            self.time_stop(None)
            return False
        else:
            self.time_forward(None)
            return True

    def time_play(self, play):
        """Automatically advance time every 100 ms"""
        if not self.playTimer:
            self.playTimer = gobject.timeout_add(100, self.time_step)

    def time_stop(self, play):
        """Stop play pressed"""
        if self.playTimer:
            gobject.source_remove(self.playTimer)
            self.playTimer = None

    def load_events(self, button):
        """Reload events file"""
        self.model.load_events(self.filenameEntry.get_text(),
            startTime=self.startTime, endTime=self.endTime)
        self.set_time_index(min(len(self.model.times) - 1,
            self.view.timeIndex))
        self.view.redraw()

class Overlay(object):
    """An Overlay is a speech bubble explaining the data in a blob"""
    def __init__(self, model, view, point, blob):
        self.model = model
        self.view = view
        self.point = point
        self.blob = blob

    def find_event(self):
        """Find the event for a changing time and a fixed blob"""
        return self.model.find_unit_event_by_time(self.blob.unit,
            self.view.time)

    def show(self, cr):
        """Draw the overlay"""
        event = self.find_event()

        if event is None:
            return

        insts = event.find_ided_objects(self.model, self.blob.picChar,
            False)

        cr.set_line_width(self.view.thinLineWidth)
        cr.translate(*(Point(0.0,0.0) - self.view.origin).to_pair())
        cr.scale(*(Point(1.0,1.0) / self.view.masterScale).to_pair())

        # Get formatted data from the insts to format into a table
        lines = list(inst.table_line() for inst in insts)

        text_size = 10.0
        cr.set_font_size(text_size)

        def text_width(str):
            xb, yb, width, height, dx, dy = cr.text_extents(str)
            return width

        # Find the maximum number of columns and the widths of each column
        num_columns = 0
        for line in lines:
            num_columns = max(num_columns, len(line))

        widths = [0] * num_columns
        for line in lines:
            for i in range(len(line)):
                widths[i] = max(widths[i], text_width(line[i]))

        # Calculate the size of the speech bubble
        column_gap = 1 * text_size
        id_width = 6 * text_size
        total_width = sum(widths) + id_width + column_gap * (num_columns + 1)
        gap_step = Point(1.0, 0.0).scale(column_gap)

        text_point = self.point
        text_step = Point(0.0, text_size)

        size = Point(total_width, text_size * len(insts))

        # Draw the speech bubble
        blobs.speech_bubble(cr, self.point, size, text_size)
        cr.set_source_color(colours.backgroundColour)
        cr.fill_preserve()
        cr.set_source_color(colours.black)
        cr.stroke()

        text_point += Point(1.0,1.0).scale(2.0 * text_size)

        id_size = Point(id_width, text_size)

        # Draw the rows in the table
        for i in range(0, len(insts)):
            row_point = text_point
            inst = insts[i]
            line = lines[i]
            blobs.striped_box(cr, row_point + id_size.scale(0.5),
                id_size, inst.id.to_striped_block(self.view.dataSelect))
            cr.set_source_color(colours.black)

            row_point += Point(1.0, 0.0).scale(id_width)
            row_point += text_step
            # Draw the columns of each row
            for j in range(0, len(line)):
                row_point += gap_step
                cr.move_to(*row_point.to_pair())
                cr.show_text(line[j])
                row_point += Point(1.0, 0.0).scale(widths[j])

            text_point += text_step

class BlobWindow(object):
    """The top-level window and its mouse control"""
    def __init__(self, model, view, controller):
        self.model = model
        self.view = view
        self.controller = controller
        self.controlbar = None
        self.window = None
        self.miniViewCount = 0

    def add_control_bar(self, controlbar):
        self.controlbar = controlbar

    def show_window(self):
        self.window = gtk.Window()

        self.vbox = gtk.VBox()
        self.vbox.set_homogeneous(False)
        if self.controlbar:
            self.vbox.pack_start(self.controlbar, False, True, 0)
        self.vbox.add(self.view.da)

        if self.miniViewCount > 0:
            self.miniViews = []
            self.miniViewHBox = gtk.HBox(homogeneous=True, spacing=2)

            # Draw mini views
            for i in range(1, self.miniViewCount + 1):
                miniView = BlobView(self.model)
                miniView.set_time_index(0)
                miniView.masterScale = Point(0.1, 0.1)
                miniView.set_da_size()
                miniView.timeOffset = i + 1
                self.miniViews.append(miniView)
                self.miniViewHBox.pack_start(miniView.da, False, True, 0)

            self.controller.otherViews = self.miniViews
            self.vbox.add(self.miniViewHBox)

        self.window.add(self.vbox)

        def show_event(picChar, event):
            print('**** Comments for', event.unit, \
                'at time', self.view.time)
            for name, value in event.pairs.items():
                print(name, '=', value)
            for comment in event.comments:
                print(comment)
            if picChar in event.visuals:
                # blocks = event.visuals[picChar].elems()
                print('**** Colour data')
                objs = event.find_ided_objects(self.model, picChar, True)
                for obj in objs:
                    print(' '.join(obj.table_line()))

        def clicked_da(da, b):
            point = Point(b.x, b.y)

            overlay = None
            for blob, centre, size in self.view.positions:
                if point.is_within_box((centre, size)):
                    event = self.model.find_unit_event_by_time(blob.unit,
                        self.view.time)
                    if event is not None:
                        if overlay is None:
                            overlay = Overlay(self.model, self.view, point,
                                blob)
                        show_event(blob.picChar, event)
            if overlay is not None:
                self.view.overlays = [overlay]
            else:
                self.view.overlays = []

            self.view.redraw()

        # Set initial size and event callbacks
        self.view.set_da_size()
        self.view.da.add_events(gtk.gdk.BUTTON_PRESS_MASK)
        self.view.da.connect('button-press-event', clicked_da)
        self.window.connect('destroy', lambda widget: gtk.main_quit())

        def resize(window, event):
            """Resize DrawingArea to match new window size"""
            size = Point(float(event.width), float(event.height))
            proportion = size / self.view.get_pic_size()
            # Preserve aspect ratio
            daScale = min(proportion.x, proportion.y)
            self.view.masterScale = Point(daScale, daScale)
            self.view.overlays = []

        self.view.da.connect('configure-event', resize)

        self.window.show_all()
