/*
 * Copyright (C) 2006, 2007, 2012 Apple Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 *
 */

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

#include <math.h>
#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/editing/position_with_affinity.h"
#include "third_party/blink/renderer/core/fileapi/file_list.h"
#include "third_party/blink/renderer/core/html/forms/html_input_element.h"
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/input_type_names.h"
#include "third_party/blink/renderer/core/layout/layout_theme.h"
#include "third_party/blink/renderer/core/paint/file_upload_control_painter.h"
#include "third_party/blink/renderer/platform/fonts/font.h"
#include "third_party/blink/renderer/platform/text/platform_locale.h"
#include "third_party/blink/renderer/platform/text/text_run.h"

namespace blink {

using namespace HTMLNames;

const int kDefaultWidthNumChars = 34;
const int kButtonShadowHeight = 2;

LayoutFileUploadControl::LayoutFileUploadControl(HTMLInputElement* input)
    : LayoutBlockFlow(input),
      can_receive_dropped_files_(input->CanReceiveDroppedFiles()) {}

LayoutFileUploadControl::~LayoutFileUploadControl() = default;

void LayoutFileUploadControl::UpdateFromElement() {
  HTMLInputElement* input = ToHTMLInputElement(GetNode());
  DCHECK_EQ(input->type(), InputTypeNames::file);

  if (HTMLInputElement* button = UploadButton()) {
    bool new_can_receive_dropped_files_state = input->CanReceiveDroppedFiles();
    if (can_receive_dropped_files_ != new_can_receive_dropped_files_state) {
      can_receive_dropped_files_ = new_can_receive_dropped_files_state;
      button->SetActive(new_can_receive_dropped_files_state);
    }
  }

  // This only supports clearing out the files, but that's OK because for
  // security reasons that's the only change the DOM is allowed to make.
  FileList* files = input->files();
  DCHECK(files);
  if (files && files->IsEmpty())
    SetShouldDoFullPaintInvalidation();
}

int LayoutFileUploadControl::MaxFilenameWidth() const {
  int upload_button_width =
      (UploadButton() && UploadButton()->GetLayoutBox())
          ? UploadButton()->GetLayoutBox()->PixelSnappedWidth()
          : 0;
  return std::max(0, ContentBoxRect().PixelSnappedWidth() -
                         upload_button_width - kAfterButtonSpacing);
}

void LayoutFileUploadControl::PaintObject(
    const PaintInfo& paint_info,
    const LayoutPoint& paint_offset) const {
  FileUploadControlPainter(*this).PaintObject(paint_info, paint_offset);
}

void LayoutFileUploadControl::ComputeIntrinsicLogicalWidths(
    LayoutUnit& min_logical_width,
    LayoutUnit& max_logical_width) const {
  // Figure out how big the filename space needs to be for a given number of
  // characters (using "0" as the nominal character).
  const UChar kCharacter = '0';
  const String character_as_string = String(&kCharacter, 1);
  const Font& font = StyleRef().GetFont();
  float min_default_label_width =
      kDefaultWidthNumChars *
      font.Width(ConstructTextRun(font, character_as_string, StyleRef(),
                                  TextRun::kAllowTrailingExpansion));

  const String label = ToHTMLInputElement(GetNode())->GetLocale().QueryString(
      WebLocalizedString::kFileButtonNoFileSelectedLabel);
  float default_label_width = font.Width(ConstructTextRun(
      font, label, StyleRef(), TextRun::kAllowTrailingExpansion));
  if (HTMLInputElement* button = UploadButton()) {
    if (LayoutObject* button_layout_object = button->GetLayoutObject())
      default_label_width += button_layout_object->MaxPreferredLogicalWidth() +
                             kAfterButtonSpacing;
  }
  max_logical_width =
      LayoutUnit(ceilf(std::max(min_default_label_width, default_label_width)));

  if (!StyleRef().Width().IsPercentOrCalc())
    min_logical_width = max_logical_width;
}

void LayoutFileUploadControl::ComputePreferredLogicalWidths() {
  DCHECK(PreferredLogicalWidthsDirty());

  min_preferred_logical_width_ = LayoutUnit();
  max_preferred_logical_width_ = LayoutUnit();
  const ComputedStyle& style_to_use = StyleRef();

  if (style_to_use.Width().IsFixed() && style_to_use.Width().Value() > 0)
    min_preferred_logical_width_ = max_preferred_logical_width_ =
        AdjustContentBoxLogicalWidthForBoxSizing(
            LayoutUnit(style_to_use.Width().Value()));
  else
    ComputeIntrinsicLogicalWidths(min_preferred_logical_width_,
                                  max_preferred_logical_width_);

  if (style_to_use.MinWidth().IsFixed() &&
      style_to_use.MinWidth().Value() > 0) {
    max_preferred_logical_width_ =
        std::max(max_preferred_logical_width_,
                 AdjustContentBoxLogicalWidthForBoxSizing(
                     LayoutUnit(style_to_use.MinWidth().Value())));
    min_preferred_logical_width_ =
        std::max(min_preferred_logical_width_,
                 AdjustContentBoxLogicalWidthForBoxSizing(
                     LayoutUnit(style_to_use.MinWidth().Value())));
  }

  if (style_to_use.MaxWidth().IsFixed()) {
    max_preferred_logical_width_ =
        std::min(max_preferred_logical_width_,
                 AdjustContentBoxLogicalWidthForBoxSizing(
                     LayoutUnit(style_to_use.MaxWidth().Value())));
    min_preferred_logical_width_ =
        std::min(min_preferred_logical_width_,
                 AdjustContentBoxLogicalWidthForBoxSizing(
                     LayoutUnit(style_to_use.MaxWidth().Value())));
  }

  int to_add = BorderAndPaddingWidth().ToInt();
  min_preferred_logical_width_ += to_add;
  max_preferred_logical_width_ += to_add;

  ClearPreferredLogicalWidthsDirty();
}

PositionWithAffinity LayoutFileUploadControl::PositionForPoint(
    const LayoutPoint&) const {
  return PositionWithAffinity();
}

HTMLInputElement* LayoutFileUploadControl::UploadButton() const {
  // FIXME: This should be on HTMLInputElement as an API like
  // innerButtonElement().
  HTMLInputElement* input = ToHTMLInputElement(GetNode());
  return ToHTMLInputElementOrNull(input->UserAgentShadowRoot()->firstChild());
}

String LayoutFileUploadControl::ButtonValue() {
  if (HTMLInputElement* button = UploadButton())
    return button->value();

  return String();
}

String LayoutFileUploadControl::FileTextValue() const {
  HTMLInputElement* input = ToHTMLInputElement(GetNode());
  DCHECK(input->files());
  return LayoutTheme::GetTheme().FileListNameForWidth(
      input->GetLocale(), input->files(), StyleRef().GetFont(),
      MaxFilenameWidth());
}

LayoutRect LayoutFileUploadControl::ControlClipRect(
    const LayoutPoint& additional_offset) const {
  LayoutRect rect(additional_offset, Size());
  rect.Expand(BorderInsets());
  rect.Expand(LayoutUnit(), LayoutUnit(kButtonShadowHeight));
  return rect;
}

// Override to allow effective ControlClipRect to be bigger than the padding
// box because of kButtonShadowHeight.
LayoutRect LayoutFileUploadControl::OverflowClipRect(
    const LayoutPoint& additional_offset,
    OverlayScrollbarClipBehavior) const {
  return ControlClipRect(additional_offset);
}

}  // namespace blink
