/*
 * Copyright (C) 2016-2018 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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 "config.h"
#import "VideoLayerManagerObjC.h"

#import "Color.h"
#import "Logging.h"
#import "TextTrackRepresentation.h"
#import "WebCoreCALayerExtras.h"
#import "WebVideoContainerLayer.h"
#import <mach/mach_init.h>
#import <mach/mach_port.h>
#import <pal/spi/cocoa/QuartzCoreSPI.h>
#import <wtf/BlockPtr.h>
#import <wtf/Logger.h>
#import <wtf/MachSendRight.h>

#import <pal/cocoa/AVFoundationSoftLink.h>

OBJC_CLASS AVPlayerLayer;

namespace WebCore {

#if !RELEASE_LOG_DISABLED
VideoLayerManagerObjC::VideoLayerManagerObjC(const Logger& logger, const void* logIdentifier)
    : m_logger(logger)
    , m_logIdentifier(logIdentifier)
{
}
#endif

VideoLayerManagerObjC::~VideoLayerManagerObjC()
{
}

PlatformLayer* VideoLayerManagerObjC::videoInlineLayer() const
{
    return m_videoInlineLayer.get();
}

void VideoLayerManagerObjC::setVideoLayer(PlatformLayer *videoLayer, IntSize contentSize)
{
    ALWAYS_LOG(LOGIDENTIFIER, contentSize.width(), ", ", contentSize.height());

    m_videoLayer = videoLayer;
    [m_videoLayer web_disableAllActions];

    m_videoInlineLayer = adoptNS([[WebVideoContainerLayer alloc] init]);
    [m_videoInlineLayer setName:@"WebVideoContainerLayer"];
    [m_videoInlineLayer setFrame:CGRectMake(0, 0, contentSize.width(), contentSize.height())];
    [m_videoInlineLayer setContentsGravity:kCAGravityResizeAspect];
    if (PAL::isAVFoundationFrameworkAvailable() && [videoLayer isKindOfClass:PAL::getAVPlayerLayerClass()])
        [m_videoInlineLayer setPlayerLayer:(AVPlayerLayer *)videoLayer];

#if ENABLE(VIDEO_PRESENTATION_MODE)
    if (m_videoFullscreenLayer) {
        [m_videoLayer setFrame:m_videoFullscreenFrame];
        [m_videoFullscreenLayer insertSublayer:m_videoLayer.get() atIndex:0];
    } else
#endif
    {
        [m_videoLayer setFrame:m_videoInlineLayer.get().bounds];
        [m_videoInlineLayer insertSublayer:m_videoLayer.get() atIndex:0];
    }
}

void VideoLayerManagerObjC::didDestroyVideoLayer()
{
    ALWAYS_LOG(LOGIDENTIFIER);

#if ENABLE(VIDEO_PRESENTATION_MODE)
    setTextTrackRepresentationLayer(nil);
#endif
    [m_videoLayer removeFromSuperlayer];

    m_videoInlineLayer = nil;
    m_videoLayer = nil;
}

#if ENABLE(VIDEO_PRESENTATION_MODE)

PlatformLayer* VideoLayerManagerObjC::videoFullscreenLayer() const
{
    return m_videoFullscreenLayer.get();
}

void VideoLayerManagerObjC::setVideoFullscreenLayer(PlatformLayer *videoFullscreenLayer, WTF::Function<void()>&& completionHandler, PlatformImagePtr currentImage)
{
    if (m_videoFullscreenLayer == videoFullscreenLayer) {
        completionHandler();
        return;
    }

    ALWAYS_LOG(LOGIDENTIFIER);

    m_videoFullscreenLayer = videoFullscreenLayer;

    [CATransaction begin];
    [CATransaction setDisableActions:YES];

    if (m_videoLayer) {
        CAContext *oldContext = [m_videoLayer context];

        if (m_videoInlineLayer && currentImage)
            [m_videoInlineLayer setContents:(__bridge id)currentImage.get()];

        if (m_videoFullscreenLayer) {
            [m_videoLayer setFrame:m_videoFullscreenFrame];
            [m_videoFullscreenLayer insertSublayer:m_videoLayer.get() atIndex:0];
        } else if (m_videoInlineLayer) {
            [m_videoLayer setFrame:[m_videoInlineLayer bounds]];
            [m_videoInlineLayer insertSublayer:m_videoLayer.get() atIndex:0];
        } else
            [m_videoLayer removeFromSuperlayer];

        CAContext *newContext = [m_videoLayer context];
        if (oldContext && newContext && oldContext != newContext) {
#if PLATFORM(MAC)
            oldContext.commitPriority = 0;
            newContext.commitPriority = 1;
#endif
            auto fencePort = MachSendRight::adopt([oldContext createFencePort]);
            [newContext setFencePort:fencePort.sendRight()];
        }
    }

    [CATransaction setCompletionBlock:makeBlockPtr([completionHandler = WTFMove(completionHandler)] {
        completionHandler();
    }).get()];

    [CATransaction commit];
}

FloatRect VideoLayerManagerObjC::videoFullscreenFrame() const
{
    return m_videoFullscreenFrame;
}

void VideoLayerManagerObjC::setVideoFullscreenFrame(FloatRect videoFullscreenFrame)
{
    ALWAYS_LOG(LOGIDENTIFIER, videoFullscreenFrame.x(), ", ", videoFullscreenFrame.y(), ", ", videoFullscreenFrame.width(), ", ", videoFullscreenFrame.height());

    m_videoFullscreenFrame = videoFullscreenFrame;
    if (!m_videoFullscreenLayer)
        return;

    [m_videoLayer setFrame:m_videoFullscreenFrame];
    syncTextTrackBounds();
}

void VideoLayerManagerObjC::updateVideoFullscreenInlineImage(PlatformImagePtr image)
{
    if (m_videoInlineLayer)
        [m_videoInlineLayer setContents:(__bridge id)image.get()];
}

#endif

bool VideoLayerManagerObjC::requiresTextTrackRepresentation() const
{
#if ENABLE(VIDEO_PRESENTATION_MODE)
    return m_videoFullscreenLayer;
#else
    return false;
#endif
}

void VideoLayerManagerObjC::syncTextTrackBounds()
{
#if ENABLE(VIDEO_PRESENTATION_MODE)
    if (!m_videoFullscreenLayer || !m_textTrackRepresentationLayer)
        return;

    if (m_textTrackRepresentationLayer.get().bounds == m_videoFullscreenFrame)
        return;

    [CATransaction begin];
    [CATransaction setDisableActions:YES];

    [m_textTrackRepresentationLayer setFrame:m_videoFullscreenFrame];

    [CATransaction commit];
#endif
}

void VideoLayerManagerObjC::setTextTrackRepresentationLayer(PlatformLayer* representationLayer)
{
#if !ENABLE(VIDEO_PRESENTATION_MODE)
    UNUSED_PARAM(representationLayer);
#else
    ALWAYS_LOG(LOGIDENTIFIER);

    if (representationLayer == m_textTrackRepresentationLayer) {
        syncTextTrackBounds();
        return;
    }

    [CATransaction begin];
    [CATransaction setDisableActions:YES];

    if (m_textTrackRepresentationLayer)
        [m_textTrackRepresentationLayer removeFromSuperlayer];

    m_textTrackRepresentationLayer = representationLayer;

    if (m_videoFullscreenLayer && m_textTrackRepresentationLayer) {
        syncTextTrackBounds();
        [m_videoFullscreenLayer addSublayer:m_textTrackRepresentationLayer.get()];
    }

    [CATransaction commit];
#endif
}

WTFLogChannel& VideoLayerManagerObjC::logChannel() const
{
    return LogMedia;
}

}
