# Copyright 2019 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import cairo
import collections
import contextlib
import ctypes
import numpy
import os
import threading
import time

import gi
gi.require_version('Gdk', '3.0')
gi.require_version('GObject', '2.0')
gi.require_version('GLib', '2.0')
gi.require_version('Gst', '1.0')
gi.require_version('GstAllocators', '1.0')
gi.require_version('GstBase', '1.0')
gi.require_version('GstGL', '1.0')
gi.require_version('GstVideo', '1.0')
from gi.repository import Gdk, GObject, GLib, Gst, GstAllocators, GstBase, GstGL, GstVideo

from OpenGL.arrays.arraydatatype import ArrayDatatype
from OpenGL.GLES3 import (
    glActiveTexture, glBindBuffer, glBindTexture, glBindVertexArray, glBlendEquation, glBlendFunc,
    glBufferData, glDeleteBuffers, glDeleteVertexArrays, glDisable, glDrawElements, glEnable,
    glEnableVertexAttribArray, glGenBuffers, glGenVertexArrays, glVertexAttribPointer,glViewport)
from OpenGL.GLES3 import (
    GL_ARRAY_BUFFER, GL_BLEND, GL_ELEMENT_ARRAY_BUFFER, GL_FALSE, GL_FLOAT, GL_FUNC_ADD,
    GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA, GL_STATIC_DRAW, GL_TEXTURE0, GL_TEXTURE_2D,
    GL_TRIANGLES, GL_UNSIGNED_SHORT)

# Gst.Buffer.map(Gst.MapFlags.WRITE) is broken, this is a workaround. See
# http://lifestyletransfer.com/how-to-make-gstreamer-buffer-writable-in-python/
# https://gitlab.gnome.org/GNOME/gobject-introspection/issues/69
class GstMapInfo(ctypes.Structure):
    _fields_ = [('memory', ctypes.c_void_p),                # GstMemory *memory
                ('flags', ctypes.c_int),                    # GstMapFlags flags
                ('data', ctypes.POINTER(ctypes.c_byte)),    # guint8 *data
                ('size', ctypes.c_size_t),                  # gsize size
                ('maxsize', ctypes.c_size_t),               # gsize maxsize
                ('user_data', ctypes.c_void_p * 4),         # gpointer user_data[4]
                ('_gst_reserved', ctypes.c_void_p * 4)]     # GST_PADDING

# ctypes imports for missing or broken introspection APIs.
libgst = ctypes.CDLL('libgstreamer-1.0.so.0')
GST_MAP_INFO_POINTER = ctypes.POINTER(GstMapInfo)
libgst.gst_buffer_map.argtypes = [ctypes.c_void_p, GST_MAP_INFO_POINTER, ctypes.c_int]
libgst.gst_buffer_map.restype = ctypes.c_int
libgst.gst_buffer_unmap.argtypes = [ctypes.c_void_p, GST_MAP_INFO_POINTER]
libgst.gst_buffer_unmap.restype = None
libgst.gst_mini_object_is_writable.argtypes = [ctypes.c_void_p]
libgst.gst_mini_object_is_writable.restype = ctypes.c_int
libgst.gst_context_writable_structure.restype = ctypes.c_void_p
libgst.gst_context_writable_structure.argtypes = [ctypes.c_void_p]
libgst.gst_structure_set.restype = ctypes.c_void_p
libgst.gst_structure_set.argtypes = [ctypes.c_void_p, ctypes.c_char_p,
        ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p]

libgstgl = ctypes.CDLL('libgstgl-1.0.so.0')
libgstgl.gst_gl_memory_get_texture_id.argtypes = [ctypes.c_void_p]
libgstgl.gst_gl_memory_get_texture_id.restype = ctypes.c_uint
libgstgl.gst_gl_sync_meta_wait_cpu.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
libgstgl.gst_gl_sync_meta_wait_cpu.restype = None

libcairo = ctypes.CDLL('libcairo.so.2')
libcairo.cairo_image_surface_create_for_data.restype = ctypes.c_void_p
libcairo.cairo_image_surface_create_for_data.argtypes = [ctypes.c_void_p,
        ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.c_int]
libcairo.cairo_surface_flush.restype = None
libcairo.cairo_surface_flush.argtypes = [ctypes.c_void_p]
libcairo.cairo_surface_destroy.restype = None
libcairo.cairo_surface_destroy.argtypes = [ctypes.c_void_p]
libcairo.cairo_format_stride_for_width.restype = ctypes.c_int
libcairo.cairo_format_stride_for_width.argtypes = [ctypes.c_int, ctypes.c_int]
libcairo.cairo_create.restype = ctypes.c_void_p
libcairo.cairo_create.argtypes = [ctypes.c_void_p]
libcairo.cairo_destroy.restype = None
libcairo.cairo_destroy.argtypes = [ctypes.c_void_p]

librsvg = ctypes.CDLL('librsvg-2.so.2')
librsvg.rsvg_handle_new_from_data.restype = ctypes.c_void_p
librsvg.rsvg_handle_new_from_data.argtypes = [ctypes.c_char_p, ctypes.c_size_t, ctypes.c_void_p]
librsvg.rsvg_handle_render_cairo.restype = ctypes.c_bool
librsvg.rsvg_handle_render_cairo.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
librsvg.rsvg_handle_close.restype = ctypes.c_bool
librsvg.rsvg_handle_close.argtypes = [ctypes.c_void_p, ctypes.c_void_p]

libgobject = ctypes.CDLL('libgobject-2.0.so.0')
libgobject.g_object_unref.restype = None
libgobject.g_object_unref.argtypes = [ctypes.c_void_p]

libgdk = ctypes.CDLL('libgdk-3.so.0')
libgdk.gdk_wayland_window_get_wl_surface.restype = ctypes.c_void_p
libgdk.gdk_wayland_window_get_wl_surface.argtypes = [ctypes.c_void_p]
libgdk.gdk_wayland_display_get_wl_display.restype = ctypes.c_void_p
libgdk.gdk_wayland_display_get_wl_display.argtypes = [ctypes.c_void_p]

@contextlib.contextmanager
def _gst_buffer_map(buffer, flags):
    ptr = hash(buffer)
    if flags & Gst.MapFlags.WRITE and libgst.gst_mini_object_is_writable(ptr) == 0:
        raise ValueError('Buffer not writable')

    mapping = GstMapInfo()
    success = libgst.gst_buffer_map(ptr, mapping, flags)
    if not success:
        raise RuntimeError('gst_buffer_map failed')
    try:
        yield ctypes.cast(mapping.data, ctypes.POINTER(ctypes.c_byte * mapping.size)).contents
    finally:
        libgst.gst_buffer_unmap(ptr, mapping)

def _get_gl_texture_id(buf):
    if not buf:
        return 0
    memory = buf.peek_memory(0)
    assert GstGL.is_gl_memory(memory)
    return libgstgl.gst_gl_memory_get_texture_id(hash(memory))

POSITIONS = numpy.array([
         1.0,  1.0,
        -1.0,  1.0,
        -1.0, -1.0,
         1.0, -1.0,
    ], dtype=numpy.float32)

TEXCOORDS = numpy.array([
         1.0, 0.0,
         0.0, 0.0,
         0.0, 1.0,
         1.0, 1.0,
    ], dtype=numpy.float32)

INDICES = numpy.array([
         0, 1, 2, 0, 2, 3
    ], dtype=numpy.uint16)

NUM_BUFFERS = 2

class DmaOverlayBuffer():
    def __init__(self, pool, glupload):
        self.glcontext = glupload.context
        res, self.dmabuf = pool.acquire_buffer()
        assert res == Gst.FlowReturn.OK
        assert GstAllocators.is_dmabuf_memory(self.dmabuf.peek_memory(0))
        with _gst_buffer_map(self.dmabuf, Gst.MapFlags.WRITE) as mapped:
            self.ptr = ctypes.addressof(mapped)
            self.len = ctypes.sizeof(mapped)
            self.clear()
        meta = GstVideo.buffer_get_video_meta(self.dmabuf)
        assert meta
        self.surface = libcairo.cairo_image_surface_create_for_data(
                self.ptr,
                int(cairo.FORMAT_ARGB32),
                meta.width,
                meta.height,
                meta.stride[0])
        self.cairo = libcairo.cairo_create(self.surface)
        res, self.gl_buffer = glupload.perform_with_buffer(self.dmabuf)
        assert res == GstGL.GLUploadReturn.DONE
        memory = self.gl_buffer.peek_memory(0)
        assert GstGL.is_gl_memory(memory)
        self.texture_id = libgstgl.gst_gl_memory_get_texture_id(hash(memory))
        self.sync = GstGL.buffer_add_gl_sync_meta(self.glcontext, self.gl_buffer)

    def __del__(self):
        if self.surface:
            libcairo.cairo_surface_destroy(self.surface)
        if self.cairo:
            libcairo.cairo_destroy(self.cairo)

    def render_svg(self, svg):
        self.wait_sync()
        self.clear()
        if svg:
            data = svg.encode()
            handle = librsvg.rsvg_handle_new_from_data(data, len(data), 0)
            if handle:
                librsvg.rsvg_handle_render_cairo(handle, self.cairo)
                librsvg.rsvg_handle_close(handle, 0)
                libgobject.g_object_unref(handle)
            libcairo.cairo_surface_flush(self.surface)

    def clear(self):
        ctypes.memset(self.ptr, 0, self.len)

    def set_sync_point(self):
        self.sync.set_sync_point(self.glcontext)

    def wait_sync(self):
        libgstgl.gst_gl_sync_meta_wait_cpu(hash(self.sync), hash(self.glcontext))


class GlSvgOverlaySink(Gst.Bin, GstVideo.VideoOverlay):
    __gstmetadata__ = ('GlSvgOverlaySink',
                       'Sink/Video',
                       'glimagesink with SVG overlays',
                       'Coral <coral-support@google.com>')
    __gsttemplates__ = (Gst.PadTemplate.new('sink',
                        Gst.PadDirection.SINK,
                        Gst.PadPresence.ALWAYS,
                        GstGL.GLUpload.get_input_template_caps()
                        ))
    __gproperties__ = {
        'svg': (str,
            'SVG data',
            'SVG overlay data',
            '',
            GObject.ParamFlags.WRITABLE
            ),
        }
    __gsignals__ = {
        'drawn': (GObject.SignalFlags.RUN_LAST, None, ())
    }

    def __init__(self):
        Gst.Bin.__init__(self)
        self.shader = None
        self.vao = 0
        self.positions_buffer = 0
        self.texcoords_buffer = 0
        self.vbo_indices = 0
        self.glcontext = None
        self.glimagesink = Gst.ElementFactory.make('glimagesink')
        self.add(self.glimagesink)
        self.add_pad(Gst.GhostPad('sink', self.glimagesink.get_static_pad('sink')))
        self.glimagesink.connect('client-draw', self.on_draw)
        self.glimagesink.connect('client-reshape', self.on_reshape)
        self.glimagesink.get_static_pad('sink').add_probe(
            Gst.PadProbeType.EVENT_UPSTREAM, self.on_glimagesink_event)
        self.render_thread = None
        self.cond = threading.Condition()
        self.rendering = False
        self.svg = None
        self.buffers = [None] * NUM_BUFFERS
        self.index = 0

        self.print_fps = int(os.environ.get('PRINT_FPS', '0'))
        self.incoming_frames = 0
        self.incoming_overlays = 0
        self.rendered_overlays = 0
        self.draws = 0
        self.fps_start = 0
        if self.print_fps:
            self.glimagesink.get_static_pad('sink').add_probe(
                Gst.PadProbeType.BUFFER, self.on_incoming_frame)

    def do_expose(self):
        self.glimagesink.expose()

    def do_handle_events(self, handle_events):
        self.glimagesink.handle_events(handle_events)

    def do_set_render_rectangle(self, x, y, width, height):
        return self.glimagesink.set_render_rectangle(x, y, width, height)

    def do_set_window_handle(self, handle):
        self.glimagesink.set_window_handle(handle)

    def on_glimagesink_event(self, pad, info):
        event = info.get_event()
        if event.type == Gst.EventType.RECONFIGURE:
            return Gst.PadProbeReturn.DROP
        return Gst.PadProbeReturn.OK

    def on_glimagesink_event(self, pad, info):
        event = info.get_event()
        if event.type == Gst.EventType.RECONFIGURE:
            return Gst.PadProbeReturn.DROP
        return Gst.PadProbeReturn.OK

    def on_incoming_frame(self, pad, info):
        self.incoming_frames += 1
        return Gst.PadProbeReturn.OK

    def post_error(self, string, debug=''):
        Gst.error(string)
        gerror = GLib.Error.new_literal(Gst.ResourceError.quark(), string, Gst.CoreError.FAILED)
        message = Gst.Message.new_error(self, gerror, debug)
        return self.post_message(message)

    def do_change_state(self, transition):
        if transition == Gst.StateChange.READY_TO_NULL:
            self.glcontext.thread_add(self.deinit_gl)
            self.glcontext = None
        elif transition == Gst.StateChange.PAUSED_TO_READY:
            with self.cond:
                self.rendering = False
                self.cond.notify_all()
            self.render_thread.join()
            self.glcontext.thread_add(self.free_buffers)

        result = Gst.Bin.do_change_state(self, transition)

        if transition == Gst.StateChange.NULL_TO_READY:
            self.glcontext = self.glimagesink.get_property('context')
            if self.glcontext:
                self.glcontext.thread_add(self.init_gl)
            else:
                self.post_error('failed to get gl context')
                result = Gst.StateChangeReturn.FAILURE
        elif transition == Gst.StateChange.READY_TO_PAUSED:
            self.try_create_buffers()
            self.rendering = True
            self.render_thread = threading.Thread(target=self.render_loop)
            self.render_thread.start()
        elif transition == Gst.StateChange.PAUSED_TO_PLAYING:
            self.try_create_buffers()

        return result

    def do_set_property(self, prop, value):
        if prop.name == 'svg':
            if not self.get_back_buffer():
                Gst.warning('Not ready to draw overlays, dropping data')
                return
            with self.cond:
                self.incoming_overlays += 1
                self.svg = value or ''
                self.cond.notify_all()
        else:
            self.glimagesink.set_property(prop, value)

    def do_get_property(self, prop):
        return self.glimagesink.get_property(prop)

    def init_gl(self, glcontext):
        assert not self.shader
        assert glcontext == self.glcontext

        self.shader = GstGL.GLShader.new_default(self.glcontext)
        a_position = self.shader.get_attribute_location('a_position')
        a_texcoord = self.shader.get_attribute_location('a_texcoord')

        self.vao = glGenVertexArrays(1)
        glBindVertexArray(self.vao)

        self.positions_buffer = glGenBuffers(1)
        glBindBuffer(GL_ARRAY_BUFFER, self.positions_buffer)
        glBufferData(GL_ARRAY_BUFFER, ArrayDatatype.arrayByteCount(POSITIONS), POSITIONS, GL_STATIC_DRAW)

        self.texcoords_buffer = glGenBuffers(1)
        glBindBuffer(GL_ARRAY_BUFFER, self.texcoords_buffer)
        glBufferData(GL_ARRAY_BUFFER, ArrayDatatype.arrayByteCount(TEXCOORDS), TEXCOORDS, GL_STATIC_DRAW)

        self.vbo_indices = glGenBuffers(1)
        glBindBuffer(GL_ARRAY_BUFFER, self.vbo_indices)
        glBufferData(GL_ARRAY_BUFFER, ArrayDatatype.arrayByteCount(INDICES), INDICES, GL_STATIC_DRAW)

        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.vbo_indices);
        glBindBuffer(GL_ARRAY_BUFFER, self.positions_buffer);
        glVertexAttribPointer.baseFunction(a_position, 2, GL_FLOAT, GL_FALSE, 0, None)
        glBindBuffer(GL_ARRAY_BUFFER, self.texcoords_buffer);
        glVertexAttribPointer.baseFunction(a_texcoord, 2, GL_FLOAT, GL_FALSE, 0, None)
        glEnableVertexAttribArray(a_position)
        glEnableVertexAttribArray(a_texcoord)

        glBindVertexArray(0)
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)
        glBindBuffer(GL_ARRAY_BUFFER, 0)

    def deinit_gl(self, glcontext):
        assert glcontext == self.glcontext
        self.overlay_shader = None
        self.shader = None
        glDeleteVertexArrays(1, [self.vao])
        self.vao = None
        glDeleteBuffers(1, [self.positions_buffer])
        self.positions_buffer = None
        glDeleteBuffers(1, [self.texcoords_buffer])
        self.texcoords_buffer = None
        glDeleteBuffers(1, [self.vbo_indices])
        self.vbo_indices = None

    def on_reshape(self, sink, context, width, height):
        sinkelement = self.glimagesink.get_by_interface(GstVideo.VideoOverlay)
        if sinkelement.width and sinkelement.height:
            src_ratio = sinkelement.width / sinkelement.height
            dst_ratio = width / height
            if src_ratio > dst_ratio:
              w = width
              h = width / src_ratio
              x = 0
              y = (height - h) / 2
            elif src_ratio < dst_ratio:
              w = height * src_ratio
              h = height
              x = (width - w) / 2
              y = 0
            else:
              w = width
              h = height;
              x = 0
              y = 0
        else:
            w = width
            h = height
            x = 0
            y = 0

        glViewport(int(x), int(y), int(w), int(h))
        return True

    # TODO: affine gltransformation support
    def on_draw(self, sink, context, sample):
        assert context == self.glcontext
        self.draws += 1

        assert context == self.glcontext
        frame_texture = _get_gl_texture_id(sample.get_buffer())
        overlay_buffer = self.get_front_buffer()
        overlay_texture = overlay_buffer.texture_id if overlay_buffer else 0

        glDisable(GL_BLEND)

        glBindVertexArray(self.vao)
        glActiveTexture(GL_TEXTURE0)
        glBindTexture(GL_TEXTURE_2D, frame_texture)

        self.shader.use()
        self.shader.set_uniform_1i('frame', 0)

        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, None)

        if overlay_texture:
            glBindTexture(GL_TEXTURE_2D, overlay_texture)
            glEnable(GL_BLEND)
            glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
            glBlendEquation(GL_FUNC_ADD)
            glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, None)

        glActiveTexture(GL_TEXTURE0)
        glBindTexture(GL_TEXTURE_2D, 0)
        glDisable(GL_BLEND)
        context.clear_shader()
        glBindVertexArray(0)

        if overlay_buffer:
            overlay_buffer.set_sync_point()

        self.emit('drawn')

        if not self.fps_start:
            self.fps_start = time.monotonic()
        elapsed = time.monotonic() - self.fps_start
        if self.print_fps and elapsed > self.print_fps:
            incoming_fps = self.incoming_frames / elapsed
            draw_fps = self.draws / elapsed
            incoming_overlay_fps = self.incoming_overlays / elapsed
            render_fps = self.rendered_overlays / elapsed
            print('glsvgoverlaysink: in frames {} ({:.2f} fps) svg {} ({:.2f} fps), rendered {} ({:.2f} fps), draw {} ({:.2f} fps)'.format(
                    self.incoming_frames, self.incoming_frames / elapsed,
                    self.incoming_overlays, self.incoming_overlays / elapsed,
                    self.rendered_overlays, self.rendered_overlays / elapsed,
                    self.draws, self.draws / elapsed))
            self.incoming_frames = 0
            self.incoming_overlays = 0
            self.rendered_overlays = 0
            self.draws = 0
            self.fps_start = time.monotonic()

        return True

    def render_loop(self):
        while True:
            with self.cond:
                rendering = self.rendering
                svg = self.svg
                self.svg = None

            if not rendering:
                break

            if svg is None:
                with self.cond:
                    self.cond.wait()
                continue

            buf = self.get_back_buffer()
            buf.render_svg(svg)
            self.rendered_overlays += 1
            self.swap_buffers()

    def try_create_buffers(self):
        if self.buffers[0]:
            return

        sink = self.glimagesink.get_by_interface(GstVideo.VideoOverlay)
        width = sink.width
        height = sink.height
        if not width or not height:
            return

        render_caps = 'video/x-raw, width={}, height={}, format=BGRA'
        gl_caps = 'video/x-raw(memory:GLMemory), width={}, height={}, format=RGBA, texture-target=2D'
        min_stride = libcairo.cairo_format_stride_for_width(int(cairo.FORMAT_ARGB32), width)
        render_caps = Gst.Caps.from_string(render_caps.format(width, height))
        gl_caps = Gst.Caps.from_string(gl_caps.format(width, height))
        glupload = GstGL.GLUpload.new(self.glcontext)
        glupload.set_caps(render_caps, gl_caps)
        query = Gst.Query.new_allocation(render_caps, True)
        glupload.propose_allocation(None, query)
        assert query.get_n_allocation_pools()
        pool, size, min_bufs, max_bufs = query.parse_nth_allocation_pool(0)
        assert pool.set_active(True)

        for i in range(0, NUM_BUFFERS):
            self.buffers[i] = DmaOverlayBuffer(pool, glupload)
        assert pool.set_active(False)

    def free_buffers(self, glcontext):
        self.buffers = [None] * NUM_BUFFERS

    def get_front_buffer(self):
        return self.buffers[(self.index - 1) % len(self.buffers)]

    def get_back_buffer(self):
        return self.buffers[self.index]

    def swap_buffers(self):
        self.index = (self.index + 1) % len(self.buffers)

    def get_default_wayland_display_context(self):
        wl_display = libgdk.gdk_wayland_display_get_wl_display(hash(Gdk.Display.get_default()))
        context = Gst.Context.new('GstWaylandDisplayHandleContextType', True)
        structure = libgst.gst_context_writable_structure(hash(context))
        libgst.gst_structure_set(structure, ctypes.c_char_p('display'.encode()),
            hash(GObject.TYPE_POINTER), wl_display, 0)
        return context

    def get_gl_display_context(self):
        if not self.glcontext:
            return None
        context = Gst.Context.new(GstGL.GL_DISPLAY_CONTEXT_TYPE, True)
        GstGL.context_set_gl_display(context, self.glcontext.get_display())
        return context

    def get_wayland_window_handle(self, widget):
        return libgdk.gdk_wayland_window_get_wl_surface(hash(widget.get_window()))

    def get_sharable_local_context(self):
        if not self.glcontext:
            return None
        _, new_glcontext = self.glcontext.get_display().create_context(self.glcontext)
        gst_context = Gst.Context.new('gst.gl.local_context', True)
        structure = libgst.gst_context_writable_structure(hash(gst_context))
        libgst.gst_structure_set(structure, ctypes.c_char_p('context'.encode()),
                hash(GObject.GType.from_name('GstGLContext')), hash(new_glcontext), 0)
        return gst_context


__gstelementfactory__ = ("glsvgoverlaysink", Gst.Rank.NONE, GlSvgOverlaySink)
