/**
 * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
 *           (C) 2008 Torch Mobile Inc. All rights reserved.
 *               (http://www.torchmobile.com/)
 *
 * 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 "core/layout/LayoutTextControl.h"

#include "core/dom/StyleChangeReason.h"
#include "core/html/TextControlElement.h"
#include "core/layout/HitTestResult.h"
#include "platform/scroll/ScrollbarTheme.h"

namespace blink {

LayoutTextControl::LayoutTextControl(TextControlElement* element)
    : LayoutBlockFlow(element) {
  DCHECK(element);
}

LayoutTextControl::~LayoutTextControl() {}

TextControlElement* LayoutTextControl::GetTextControlElement() const {
  return ToTextControlElement(GetNode());
}

HTMLElement* LayoutTextControl::InnerEditorElement() const {
  return GetTextControlElement()->InnerEditorElement();
}

void LayoutTextControl::StyleDidChange(StyleDifference diff,
                                       const ComputedStyle* old_style) {
  LayoutBlockFlow::StyleDidChange(diff, old_style);
  Element* inner_editor = InnerEditorElement();
  if (!inner_editor)
    return;
  LayoutBlock* inner_editor_layout_object =
      ToLayoutBlock(inner_editor->GetLayoutObject());
  if (inner_editor_layout_object) {
    // We may have set the width and the height in the old style in layout().
    // Reset them now to avoid getting a spurious layout hint.
    inner_editor_layout_object->MutableStyleRef().SetHeight(Length());
    inner_editor_layout_object->MutableStyleRef().SetWidth(Length());
    inner_editor_layout_object->SetStyle(CreateInnerEditorStyle(StyleRef()));
    inner_editor->SetNeedsStyleRecalc(
        kSubtreeStyleChange,
        StyleChangeReasonForTracing::Create(StyleChangeReason::kControl));
  }
  GetTextControlElement()->UpdatePlaceholderVisibility();
}

static inline void UpdateUserModifyProperty(TextControlElement& node,
                                            ComputedStyle& style) {
  style.SetUserModify(node.IsDisabledOrReadOnly()
                          ? EUserModify::kReadOnly
                          : EUserModify::kReadWritePlaintextOnly);
}

void LayoutTextControl::AdjustInnerEditorStyle(
    ComputedStyle& text_block_style) const {
  // The inner block, if present, always has its direction set to LTR,
  // so we need to inherit the direction and unicode-bidi style from the
  // element.
  text_block_style.SetDirection(Style()->Direction());
  text_block_style.SetUnicodeBidi(Style()->GetUnicodeBidi());
  text_block_style.SetUserSelect(EUserSelect::kText);

  UpdateUserModifyProperty(*GetTextControlElement(), text_block_style);
}

int LayoutTextControl::TextBlockLogicalHeight() const {
  return (LogicalHeight() - BorderAndPaddingLogicalHeight()).ToInt();
}

int LayoutTextControl::TextBlockLogicalWidth() const {
  Element* inner_editor = InnerEditorElement();
  DCHECK(inner_editor);

  LayoutUnit unit_width = LogicalWidth() - BorderAndPaddingLogicalWidth();
  if (inner_editor->GetLayoutObject())
    unit_width -= inner_editor->GetLayoutBox()->PaddingStart() +
                  inner_editor->GetLayoutBox()->PaddingEnd();

  return unit_width.ToInt();
}

void LayoutTextControl::UpdateFromElement() {
  Element* inner_editor = InnerEditorElement();
  if (inner_editor && inner_editor->GetLayoutObject())
    UpdateUserModifyProperty(
        *GetTextControlElement(),
        inner_editor->GetLayoutObject()->MutableStyleRef());
}

int LayoutTextControl::ScrollbarThickness() const {
  // FIXME: We should get the size of the scrollbar from the LayoutTheme
  // instead.
  return ScrollbarTheme::GetTheme().ScrollbarThickness();
}

void LayoutTextControl::ComputeLogicalHeight(
    LayoutUnit logical_height,
    LayoutUnit logical_top,
    LogicalExtentComputedValues& computed_values) const {
  HTMLElement* inner_editor = InnerEditorElement();
  DCHECK(inner_editor);
  if (LayoutBox* inner_editor_box = inner_editor->GetLayoutBox()) {
    LayoutUnit non_content_height = inner_editor_box->BorderAndPaddingHeight() +
                                    inner_editor_box->MarginHeight();
    logical_height = ComputeControlLogicalHeight(
        inner_editor_box->LineHeight(true, kHorizontalLine,
                                     kPositionOfInteriorLineBoxes),
        non_content_height);

    // We are able to have a horizontal scrollbar if the overflow style is
    // scroll, or if its auto and there's no word wrap.
    if (Style()->OverflowInlineDirection() == EOverflow::kScroll ||
        (Style()->OverflowInlineDirection() == EOverflow::kAuto &&
         inner_editor->GetLayoutObject()->Style()->OverflowWrap() ==
             EOverflowWrap::kNormal))
      logical_height += ScrollbarThickness();

    // FIXME: The logical height of the inner text box should have been added
    // before calling computeLogicalHeight to avoid this hack.
    SetIntrinsicContentLogicalHeight(logical_height);

    logical_height += BorderAndPaddingHeight();
  }

  LayoutBox::ComputeLogicalHeight(logical_height, logical_top, computed_values);
}

void LayoutTextControl::HitInnerEditorElement(
    HitTestResult& result,
    const LayoutPoint& point_in_container,
    const LayoutPoint& accumulated_offset) {
  HTMLElement* inner_editor = InnerEditorElement();
  if (!inner_editor->GetLayoutObject())
    return;

  LayoutPoint adjusted_location = accumulated_offset + Location();
  LayoutPoint local_point =
      point_in_container -
      ToLayoutSize(adjusted_location +
                   inner_editor->GetLayoutBox()->Location());
  if (HasOverflowClip())
    local_point += ScrolledContentOffset();
  result.SetNodeAndPosition(inner_editor, local_point);
}

static const char* const kFontFamiliesWithInvalidCharWidth[] = {
    "American Typewriter",
    "Arial Hebrew",
    "Chalkboard",
    "Cochin",
    "Corsiva Hebrew",
    "Courier",
    "Euphemia UCAS",
    "Geneva",
    "Gill Sans",
    "Hei",
    "Helvetica",
    "Hoefler Text",
    "InaiMathi",
    "Kai",
    "Lucida Grande",
    "Marker Felt",
    "Monaco",
    "Mshtakan",
    "New Peninim MT",
    "Osaka",
    "Raanana",
    "STHeiti",
    "Symbol",
    "Times",
    "Apple Braille",
    "Apple LiGothic",
    "Apple LiSung",
    "Apple Symbols",
    "AppleGothic",
    "AppleMyungjo",
    "#GungSeo",
    "#HeadLineA",
    "#PCMyungjo",
    "#PilGi",
};

// For font families where any of the fonts don't have a valid entry in the OS/2
// table for avgCharWidth, fallback to the legacy webkit behavior of getting the
// avgCharWidth from the width of a '0'. This only seems to apply to a fixed
// number of Mac fonts, but, in order to get similar rendering across platforms,
// we do this check for all platforms.
bool LayoutTextControl::HasValidAvgCharWidth(const SimpleFontData* font_data,
                                             const AtomicString& family) {
  // Some fonts match avgCharWidth to CJK full-width characters.
  // Heuristic check to avoid such fonts.
  DCHECK(font_data);
  if (!font_data)
    return false;
  const FontMetrics& metrics = font_data->GetFontMetrics();
  if (metrics.HasZeroWidth() &&
      font_data->AvgCharWidth() > metrics.ZeroWidth() * 1.7)
    return false;

  static HashSet<AtomicString>* font_families_with_invalid_char_width_map =
      nullptr;

  if (family.IsEmpty())
    return false;

  if (!font_families_with_invalid_char_width_map) {
    font_families_with_invalid_char_width_map = new HashSet<AtomicString>;

    for (size_t i = 0; i < WTF_ARRAY_LENGTH(kFontFamiliesWithInvalidCharWidth);
         ++i)
      font_families_with_invalid_char_width_map->insert(
          AtomicString(kFontFamiliesWithInvalidCharWidth[i]));
  }

  return !font_families_with_invalid_char_width_map->Contains(family);
}

float LayoutTextControl::GetAvgCharWidth(const AtomicString& family) const {
  const Font& font = Style()->GetFont();

  const SimpleFontData* primary_font = font.PrimaryFont();
  if (primary_font && HasValidAvgCharWidth(primary_font, family))
    return roundf(primary_font->AvgCharWidth());

  const UChar kCh = '0';
  const String str = String(&kCh, 1);
  TextRun text_run =
      ConstructTextRun(font, str, StyleRef(), TextRun::kAllowTrailingExpansion);
  return font.Width(text_run);
}

float LayoutTextControl::ScaleEmToUnits(int x) const {
  // This matches the unitsPerEm value for MS Shell Dlg and Courier New from the
  // "head" font table.
  float units_per_em = 2048.0f;
  return roundf(Style()->GetFont().GetFontDescription().ComputedSize() * x /
                units_per_em);
}

void LayoutTextControl::ComputeIntrinsicLogicalWidths(
    LayoutUnit& min_logical_width,
    LayoutUnit& max_logical_width) const {
  // Use average character width. Matches IE.
  AtomicString family =
      Style()->GetFont().GetFontDescription().Family().Family();
  max_logical_width = PreferredContentLogicalWidth(
      const_cast<LayoutTextControl*>(this)->GetAvgCharWidth(family));
  if (InnerEditorElement()) {
    if (LayoutBox* inner_editor_layout_box =
            InnerEditorElement()->GetLayoutBox())
      max_logical_width += inner_editor_layout_box->PaddingStart() +
                           inner_editor_layout_box->PaddingEnd();
  }
  if (!Style()->LogicalWidth().IsPercentOrCalc())
    min_logical_width = max_logical_width;
}

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

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

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

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

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

  LayoutUnit to_add = BorderAndPaddingLogicalWidth();

  min_preferred_logical_width_ += to_add;
  max_preferred_logical_width_ += to_add;

  ClearPreferredLogicalWidthsDirty();
}

void LayoutTextControl::AddOutlineRects(Vector<LayoutRect>& rects,
                                        const LayoutPoint& additional_offset,
                                        IncludeBlockVisualOverflowOrNot) const {
  rects.push_back(LayoutRect(additional_offset, Size()));
}

LayoutObject* LayoutTextControl::LayoutSpecialExcludedChild(
    bool relayout_children,
    SubtreeLayoutScope& layout_scope) {
  HTMLElement* placeholder =
      ToTextControlElement(GetNode())->PlaceholderElement();
  LayoutObject* placeholder_layout_object =
      placeholder ? placeholder->GetLayoutObject() : nullptr;
  if (!placeholder_layout_object)
    return nullptr;
  if (relayout_children)
    layout_scope.SetChildNeedsLayout(placeholder_layout_object);
  return placeholder_layout_object;
}

LayoutUnit LayoutTextControl::FirstLineBoxBaseline() const {
  LayoutUnit result = LayoutBlock::FirstLineBoxBaseline();
  if (result != -1)
    return result;

  // When the text is empty, |LayoutBlock::firstLineBoxBaseline()| cannot
  // compute the baseline because lineboxes do not exist.
  Element* inner_editor = InnerEditorElement();
  if (!inner_editor || !inner_editor->GetLayoutObject())
    return LayoutUnit(-1);

  LayoutBlock* inner_editor_layout_object =
      ToLayoutBlock(inner_editor->GetLayoutObject());
  const SimpleFontData* font_data =
      inner_editor_layout_object->Style(true)->GetFont().PrimaryFont();
  DCHECK(font_data);
  if (!font_data)
    return LayoutUnit(-1);

  LayoutUnit baseline(font_data->GetFontMetrics().Ascent(kAlphabeticBaseline));
  for (LayoutObject* box = inner_editor_layout_object; box && box != this;
       box = box->Parent()) {
    if (box->IsBox())
      baseline += ToLayoutBox(box)->LogicalTop();
  }
  return baseline;
}

}  // namespace blink
