/*
 * Copyright (C) 2007, 2008, 2009, 2010 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 COMPUTER, 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 COMPUTER, 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.
 */

#include "third_party/blink/renderer/core/layout/layout_video.h"

#include "third_party/blink/public/platform/web_size.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/html/media/html_video_element.h"
#include "third_party/blink/renderer/core/html/media/media_element_parser_helpers.h"
#include "third_party/blink/renderer/core/paint/video_painter.h"

namespace blink {

using namespace HTMLNames;

LayoutVideo::LayoutVideo(HTMLVideoElement* video) : LayoutMedia(video) {
  SetIntrinsicSize(CalculateIntrinsicSize());
}

LayoutVideo::~LayoutVideo() = default;

LayoutSize LayoutVideo::DefaultSize() {
  return LayoutSize(kDefaultWidth, kDefaultHeight);
}

void LayoutVideo::IntrinsicSizeChanged() {
  if (VideoElement()->ShouldDisplayPosterImage())
    LayoutMedia::IntrinsicSizeChanged();
  UpdateIntrinsicSize();
}

void LayoutVideo::UpdateIntrinsicSize() {
  LayoutSize size = CalculateIntrinsicSize();
  size.Scale(StyleRef().EffectiveZoom());

  // Never set the element size to zero when in a media document.
  if (size.IsEmpty() && GetNode()->ownerDocument() &&
      GetNode()->ownerDocument()->IsMediaDocument())
    return;

  if (size == IntrinsicSize())
    return;

  SetIntrinsicSize(size);
  SetPreferredLogicalWidthsDirty();
  SetNeedsLayoutAndFullPaintInvalidation(
      LayoutInvalidationReason::kSizeChanged);
}

LayoutSize LayoutVideo::CalculateIntrinsicSize() {
  HTMLVideoElement* video = VideoElement();
  DCHECK(video);

  if (RuntimeEnabledFeatures::ExperimentalProductivityFeaturesEnabled() &&
      !video->GetOverriddenIntrinsicSize().IsEmpty())
    return LayoutSize(video->GetOverriddenIntrinsicSize());

  // Spec text from 4.8.6
  //
  // The intrinsic width of a video element's playback area is the intrinsic
  // width of the video resource, if that is available; otherwise it is the
  // intrinsic width of the poster frame, if that is available; otherwise it is
  // 300 CSS pixels.
  //
  // The intrinsic height of a video element's playback area is the intrinsic
  // height of the video resource, if that is available; otherwise it is the
  // intrinsic height of the poster frame, if that is available; otherwise it is
  // 150 CSS pixels.
  WebMediaPlayer* web_media_player = MediaElement()->GetWebMediaPlayer();
  if (web_media_player &&
      video->getReadyState() >= HTMLVideoElement::kHaveMetadata) {
    IntSize size = web_media_player->NaturalSize();
    if (!size.IsEmpty())
      return LayoutSize(size);
  }

  if (video->ShouldDisplayPosterImage() && !cached_image_size_.IsEmpty() &&
      !ImageResource()->ErrorOccurred())
    return cached_image_size_;

  return DefaultSize();
}

void LayoutVideo::ImageChanged(WrappedImagePtr new_image,
                               CanDeferInvalidation defer,
                               const IntRect* rect) {
  LayoutMedia::ImageChanged(new_image, defer, rect);

  // Cache the image intrinsic size so we can continue to use it to draw the
  // image correctly even if we know the video intrinsic size but aren't able to
  // draw video frames yet (we don't want to scale the poster to the video size
  // without keeping aspect ratio).
  if (VideoElement()->ShouldDisplayPosterImage())
    cached_image_size_ = IntrinsicSize();

  // The intrinsic size is now that of the image, but in case we already had the
  // intrinsic size of the video we call this here to restore the video size.
  UpdateIntrinsicSize();
}

bool LayoutVideo::ShouldDisplayVideo() const {
  return !VideoElement()->ShouldDisplayPosterImage();
}

void LayoutVideo::PaintReplaced(const PaintInfo& paint_info,
                                const LayoutPoint& paint_offset) const {
  VideoPainter(*this).PaintReplaced(paint_info, paint_offset);
}

void LayoutVideo::UpdateLayout() {
  UpdatePlayer();
  LayoutMedia::UpdateLayout();
}

HTMLVideoElement* LayoutVideo::VideoElement() const {
  return ToHTMLVideoElement(GetNode());
}

void LayoutVideo::UpdateFromElement() {
  LayoutMedia::UpdateFromElement();
  UpdatePlayer();

  // If the DisplayMode of the video changed, then we need to paint.
  SetShouldDoFullPaintInvalidation();
}

void LayoutVideo::UpdatePlayer() {
  UpdateIntrinsicSize();

  WebMediaPlayer* media_player = MediaElement()->GetWebMediaPlayer();
  if (!media_player)
    return;

  if (!VideoElement()->InActiveDocument())
    return;

  VideoElement()->SetNeedsCompositingUpdate();
}

LayoutUnit LayoutVideo::ComputeReplacedLogicalWidth(
    ShouldComputePreferred should_compute_preferred) const {
  return LayoutReplaced::ComputeReplacedLogicalWidth(should_compute_preferred);
}

LayoutUnit LayoutVideo::ComputeReplacedLogicalHeight(
    LayoutUnit estimated_used_width) const {
  return LayoutReplaced::ComputeReplacedLogicalHeight(estimated_used_width);
}

LayoutUnit LayoutVideo::MinimumReplacedHeight() const {
  return LayoutReplaced::MinimumReplacedHeight();
}

LayoutRect LayoutVideo::ReplacedContentRect() const {
  if (ShouldDisplayVideo()) {
    // Video codecs may need to restart from an I-frame when the output is
    // resized. Round size in advance to avoid 1px snap difference.
    return PreSnappedRectForPersistentSizing(ComputeObjectFit());
  }
  // If we are displaying the poster image no pre-rounding is needed, but the
  // size of the image should be used for fitting instead.
  return ComputeObjectFit(&cached_image_size_);
}

bool LayoutVideo::SupportsAcceleratedRendering() const {
  return !!MediaElement()->CcLayer();
}

CompositingReasons LayoutVideo::AdditionalCompositingReasons() const {
  HTMLMediaElement* element = ToHTMLMediaElement(GetNode());
  if (element->IsFullscreen() && element->UsesOverlayFullscreenVideo())
    return CompositingReason::kVideo;

  if (ShouldDisplayVideo() && SupportsAcceleratedRendering())
    return CompositingReason::kVideo;

  return CompositingReason::kNone;
}

void LayoutVideo::UpdateAfterLayout() {
  LayoutBox::UpdateAfterLayout();
  // Report violation of unsized-media policy.
  if (auto* video_element = ToHTMLVideoElementOrNull(GetNode())) {
    if (video_element->IsDefaultIntrinsicSize())
      MediaElementParserHelpers::ReportUnsizedMediaViolation(this);
  }
}

}  // namespace blink
