# -*- coding: utf-8 -*-
#
# PhotoFilmStrip - Creates movies out of your pictures.
#
# Copyright (C) 2011 Jens Goepfert
#

import array
import time

try:
    import wx
    import cairo
except (ImportError, RuntimeError):
    cairo = None

from photofilmstrip.core.BaseRenderer import BaseRenderer, FinalizeHandler


class CairoRenderer(BaseRenderer):

    def __init__(self):
        BaseRenderer.__init__(self)
        self._ctx = None
        self._mainClock = Clock()
        self._framerate = None

        self._screen = wx.Frame(wx.GetApp().GetTopWindow(),
                                style=wx.DEFAULT_FRAME_STYLE | wx.RESIZE_BORDER)
        self._screen.Bind(wx.EVT_PAINT, self.OnPaint)
        self._screen.Show()

    @staticmethod
    def GetName():
        return _("Preview")

    @staticmethod
    def CheckDependencies(msgList):
        BaseRenderer.CheckDependencies(msgList)
        if cairo is None:
            msgList.append("cairo not installed!")

    def GetFinalizeHandler(self):
        '''
        :rtype: FinalizeHandler
        '''
        return PilToCairoFinalizeHandler()

    def ToSink(self, data):
        self._ctx = data
        self._mainClock.tick(self._framerate)

        wx.CallAfter(self._screen.Refresh)

    def ProcessAbort(self):
        wx.CallAfter(self._screen.Destroy)

    def Prepare(self):
        self._screen.SetClientSize(*self.GetProfile().GetResolution())

        self._framerate = self.GetProfile().GetFrameRate().AsFloat()
        self._mainClock.reset()

    def OnPaint(self, event):
        dc = wx.BufferedPaintDC(self._screen)
#        dc.SetBackground(wx.Brush('black'))
#        dc.Clear()

        if self._ctx:
            w = self._ctx.get_width()
            h = self._ctx.get_height()
            data = self._ctx.get_data()
            wxbmp = wx.Bitmap.FromBufferRGBA(w, h, data)
            dc.DrawBitmap(wxbmp, 0, 0)

        event.Skip()

    def Finalize(self):
        wx.CallAfter(self._screen.Destroy)


class PilToCairoFinalizeHandler(FinalizeHandler):

    def ProcessFinalize(self, pilImg):
        pilImg = pilImg.copy()
        w, h = pilImg.size
        data = pilImg.convert('RGBA').tobytes()
        buff = array.array('B', data)
        cairoImage = cairo.ImageSurface.create_for_data(# pylint: disable=no-member
            buff, cairo.FORMAT_ARGB32, w, h)  # pylint: disable=no-member
#        cairoImage = cairo.ImageSurface.create_for_data(buff, cairo.FORMAT_RGB24, w, h)
        return cairoImage


class Clock:

    def __init__(self):
        self.fps = 0.0
        self.fps_count = 0
        self.start = 0

    def reset(self):
        self.start = time.time()

    def tick(self, framerate):
        nowtime = time.time()
        self.fps_count += 1

        timepassed = nowtime - self.start

        self.fps = 1.0 / (timepassed / self.fps_count)

        endtime = (1.0 / framerate) * self.fps_count
        delay = endtime - timepassed
        if delay < 0:
            delay = 0
        time.sleep(delay)

    def get_fps(self):
        return self.fps


def get_fps(clock, value):
    fps = clock.get_fps()
    tol = 0.1
#    print fps, abs(fps - value), abs(fps * tol)
    return not (fps > 1 and abs(fps - value) <= abs(fps * tol))

