# Copyright 2004-2013 Tom Rothamel <pytom@bishoujo.us>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

import renpy.display
import renpy.audio

# The movie displayable that's currently being shown on the screen.
current_movie = None

# True if the movie that is currently displaying is in fullscreen mode,
# False if it's a smaller size.
fullscreen = False

# The size of a Movie object that hasn't had an explicit size set.
default_size = (400, 300)

# The file we allocated the surface for.
surface_file = None

# The surface to display the movie on, if not fullscreen.
surface = None

def movie_stop(clear=True, only_fullscreen=False):
    """
    Stops the currently playing movie.
    """

    if (not fullscreen) and only_fullscreen:
        return

    renpy.audio.music.stop(channel='movie')

    
def movie_start(filename, size=None, loops=0):
    """
    This starts a movie playing. 
    """
    
    if renpy.game.less_updates:
        return

    global default_size
    
    if size is not None:
        default_size = size
    
    filename = [ filename ]

    if loops == -1:
        loop = True
    else:
        loop = False
        filename = filename * (loops + 1)

    renpy.audio.music.play(filename, channel='movie', loop=loop)

movie_start_fullscreen = movie_start
movie_start_displayable = movie_start

def early_interact():
    """
    Called early in the interact process, to clear out the fullscreen
    flag.
    """

    global fullscreen
    global current_movie
    
    fullscreen = True
    current_movie = None
    

def interact():
    """
    This is called each time the screen is redrawn. It helps us decide if
    the movie should be displayed fullscreen or not.
    """

    global surface
    global surface_file
    
    if not renpy.audio.music.get_playing("movie"):
        surface = None
        surface_file = None
        return False
        
    if fullscreen: 
        return True
    else:
        return False

def get_movie_texture():
    """
    Gets a movie texture we can draw to the screen.
    """
    
    global surface
    global surface_file

    playing = renpy.audio.music.get_playing("movie")

    pss = renpy.audio.audio.pss

    if pss:
        size = pss.movie_size()
    else:
        size = (64, 64)

    if (surface is None) or (surface.get_size() != size) or (surface_file != playing):
        surface = renpy.display.pgrender.surface(size, False)
        surface_file = playing
        surface.fill((0, 0, 0, 255))

    tex = None

    if playing is not None:
        renpy.display.render.mutated_surface(surface)
        tex = renpy.display.draw.load_texture(surface, True)

    return tex


def render_movie(width, height):
    tex = get_movie_texture()
    
    if tex is None:
        return None
    
    sw, sh = tex.get_size()
    
    scale = min(1.0 * width / sw, 1.0 * height / sh)
    
    dw = scale * sw
    dh = scale * sh
    
    rv = renpy.display.render.Render(width, height, opaque=True)
    rv.forward = renpy.display.render.Matrix2D(1.0 / scale, 0.0, 0.0, 1.0 / scale)
    rv.reverse = renpy.display.render.Matrix2D(scale, 0.0, 0.0, scale)
    rv.blit(tex, (int((width - dw) / 2), int((height - dh) / 2)))

    return rv

class Movie(renpy.display.core.Displayable):
    """
    This is a displayable that shows the current movie.
    """

    fullscreen = False
    
    def __init__(self, fps=24, size=None, **properties):
        """
        @param fps: The framerate that the movie should be shown at.
        """
        super(Movie, self).__init__(**properties)
        self.size = size
        
    def render(self, width, height, st, at):
        
        size = self.size
        
        if size is None:
            size = default_size

        width, height = size
    
        rv = render_movie(width, height)
        
        if rv is None:
            rv = renpy.display.render.Render(0, 0)

        # Usually we get redrawn when the frame is ready - but we want
        # the movie to disappear if it's ended, or if it hasn't started
        # yet.
        renpy.display.render.redraw(self, 0.1)
    
        return rv
    
            
    def per_interact(self):
        global fullscreen
        fullscreen = False

        global current_movie
        current_movie = self
        
            
def playing():
    return renpy.audio.music.get_playing("movie")

def frequent():
    """
    Called to update the video playback. Returns true if a video refresh is 
    needed, false otherwise.
    """

    if not playing():
        return 0

    pss = renpy.audio.audio.pss
 
    if pss.needs_alloc():
    
        if renpy.display.video.fullscreen and renpy.display.draw.fullscreen_surface:
            surf = renpy.display.draw.fullscreen_surface
        else:
            get_movie_texture()
            surf = renpy.display.scale.real(surface)
    
        pss.alloc_event(surf)

    rv = pss.refresh_event()

    if rv and current_movie is not None:
        renpy.display.render.redraw(current_movie, 0)
         
    return rv    
