// Copyright (c) 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "web/PopupMenuImpl.h"

#include "core/HTMLNames.h"
#include "core/css/CSSFontSelector.h"
#include "core/dom/ElementTraversal.h"
#include "core/dom/ExecutionContextTask.h"
#include "core/dom/NodeComputedStyle.h"
#include "core/dom/StyleEngine.h"
#include "core/dom/TaskRunnerHelper.h"
#include "core/events/ScopedEventQueue.h"
#include "core/frame/FrameView.h"
#include "core/frame/LocalFrame.h"
#include "core/html/HTMLHRElement.h"
#include "core/html/HTMLOptGroupElement.h"
#include "core/html/HTMLOptionElement.h"
#include "core/html/HTMLSelectElement.h"
#include "core/html/parser/HTMLParserIdioms.h"
#include "core/layout/LayoutTheme.h"
#include "core/page/PagePopup.h"
#include "platform/geometry/IntRect.h"
#include "platform/text/PlatformLocale.h"
#include "public/platform/Platform.h"
#include "public/web/WebColorChooser.h"
#include "web/ChromeClientImpl.h"
#include "web/WebViewImpl.h"

namespace blink {

namespace {

const char* fontWeightToString(FontWeight weight) {
  switch (weight) {
    case FontWeight100:
      return "100";
    case FontWeight200:
      return "200";
    case FontWeight300:
      return "300";
    case FontWeight400:
      return "400";
    case FontWeight500:
      return "500";
    case FontWeight600:
      return "600";
    case FontWeight700:
      return "700";
    case FontWeight800:
      return "800";
    case FontWeight900:
      return "900";
  }
  NOTREACHED();
  return nullptr;
}

// TODO crbug.com/516675 Add stretch to serialization

const char* fontStyleToString(FontStyle style) {
  switch (style) {
    case FontStyleNormal:
      return "normal";
    case FontStyleOblique:
      return "oblique";
    case FontStyleItalic:
      return "italic";
  }
  NOTREACHED();
  return nullptr;
}

const char* textTransformToString(ETextTransform transform) {
  switch (transform) {
    case ETextTransform::kCapitalize:
      return "capitalize";
    case ETextTransform::kUppercase:
      return "uppercase";
    case ETextTransform::kLowercase:
      return "lowercase";
    case ETextTransform::kNone:
      return "none";
  }
  NOTREACHED();
  return "";
}

}  // anonymous namespace

class PopupMenuCSSFontSelector : public CSSFontSelector,
                                 private CSSFontSelectorClient {
  USING_GARBAGE_COLLECTED_MIXIN(PopupMenuCSSFontSelector);

 public:
  static PopupMenuCSSFontSelector* create(Document* document,
                                          CSSFontSelector* ownerFontSelector) {
    return new PopupMenuCSSFontSelector(document, ownerFontSelector);
  }

  ~PopupMenuCSSFontSelector();

  // We don't override willUseFontData() for now because the old PopupListBox
  // only worked with fonts loaded when opening the popup.
  PassRefPtr<FontData> getFontData(const FontDescription&,
                                   const AtomicString&) override;

  DECLARE_VIRTUAL_TRACE();

 private:
  PopupMenuCSSFontSelector(Document*, CSSFontSelector*);

  void fontsNeedUpdate(CSSFontSelector*) override;

  Member<CSSFontSelector> m_ownerFontSelector;
};

PopupMenuCSSFontSelector::PopupMenuCSSFontSelector(
    Document* document,
    CSSFontSelector* ownerFontSelector)
    : CSSFontSelector(document), m_ownerFontSelector(ownerFontSelector) {
  m_ownerFontSelector->registerForInvalidationCallbacks(this);
}

PopupMenuCSSFontSelector::~PopupMenuCSSFontSelector() {}

PassRefPtr<FontData> PopupMenuCSSFontSelector::getFontData(
    const FontDescription& description,
    const AtomicString& name) {
  return m_ownerFontSelector->getFontData(description, name);
}

void PopupMenuCSSFontSelector::fontsNeedUpdate(CSSFontSelector* fontSelector) {
  dispatchInvalidationCallbacks();
}

DEFINE_TRACE(PopupMenuCSSFontSelector) {
  visitor->trace(m_ownerFontSelector);
  CSSFontSelector::trace(visitor);
  CSSFontSelectorClient::trace(visitor);
}

// ----------------------------------------------------------------

class PopupMenuImpl::ItemIterationContext {
  STACK_ALLOCATED();

 public:
  ItemIterationContext(const ComputedStyle& style, SharedBuffer* buffer)
      : m_baseStyle(style),
        m_backgroundColor(
            style.visitedDependentColor(CSSPropertyBackgroundColor)),
        m_listIndex(0),
        m_isInGroup(false),
        m_buffer(buffer) {
    DCHECK(m_buffer);
#if OS(LINUX)
    // On other platforms, the <option> background color is the same as the
    // <select> background color. On Linux, that makes the <option>
    // background color very dark, so by default, try to use a lighter
    // background color for <option>s.
    if (LayoutTheme::theme().systemColor(CSSValueButtonface) ==
        m_backgroundColor)
      m_backgroundColor = LayoutTheme::theme().systemColor(CSSValueMenu);
#endif
  }

  void serializeBaseStyle() {
    DCHECK(!m_isInGroup);
    PagePopupClient::addString("baseStyle: {", m_buffer);
    addProperty("backgroundColor", m_backgroundColor.serialized(), m_buffer);
    addProperty(
        "color",
        baseStyle().visitedDependentColor(CSSPropertyColor).serialized(),
        m_buffer);
    addProperty("textTransform",
                String(textTransformToString(baseStyle().textTransform())),
                m_buffer);
    addProperty("fontSize", baseFont().computedPixelSize(), m_buffer);
    addProperty("fontStyle", String(fontStyleToString(baseFont().style())),
                m_buffer);
    addProperty("fontVariant",
                baseFont().variantCaps() == FontDescription::SmallCaps
                    ? String("small-caps")
                    : String(),
                m_buffer);

    PagePopupClient::addString("fontFamily: [", m_buffer);
    for (const FontFamily* f = &baseFont().family(); f; f = f->next()) {
      addJavaScriptString(f->family().getString(), m_buffer);
      if (f->next())
        PagePopupClient::addString(",", m_buffer);
    }
    PagePopupClient::addString("]", m_buffer);
    PagePopupClient::addString("},\n", m_buffer);
  }

  Color backgroundColor() const {
    return m_isInGroup
               ? m_groupStyle->visitedDependentColor(CSSPropertyBackgroundColor)
               : m_backgroundColor;
  }
  // Do not use baseStyle() for background-color, use backgroundColor()
  // instead.
  const ComputedStyle& baseStyle() {
    return m_isInGroup ? *m_groupStyle : m_baseStyle;
  }
  const FontDescription& baseFont() {
    return m_isInGroup ? m_groupStyle->getFontDescription()
                       : m_baseStyle.getFontDescription();
  }
  void startGroupChildren(const ComputedStyle& groupStyle) {
    DCHECK(!m_isInGroup);
    PagePopupClient::addString("children: [", m_buffer);
    m_isInGroup = true;
    m_groupStyle = &groupStyle;
  }
  void finishGroupIfNecessary() {
    if (!m_isInGroup)
      return;
    PagePopupClient::addString("],},\n", m_buffer);
    m_isInGroup = false;
    m_groupStyle = nullptr;
  }

  const ComputedStyle& m_baseStyle;
  Color m_backgroundColor;
  const ComputedStyle* m_groupStyle;

  unsigned m_listIndex;
  bool m_isInGroup;
  SharedBuffer* m_buffer;
};

// ----------------------------------------------------------------

PopupMenuImpl* PopupMenuImpl::create(ChromeClientImpl* chromeClient,
                                     HTMLSelectElement& ownerElement) {
  return new PopupMenuImpl(chromeClient, ownerElement);
}

PopupMenuImpl::PopupMenuImpl(ChromeClientImpl* chromeClient,
                             HTMLSelectElement& ownerElement)
    : m_chromeClient(chromeClient),
      m_ownerElement(ownerElement),
      m_popup(nullptr),
      m_needsUpdate(false) {}

PopupMenuImpl::~PopupMenuImpl() {
  DCHECK(!m_popup);
}

DEFINE_TRACE(PopupMenuImpl) {
  visitor->trace(m_chromeClient);
  visitor->trace(m_ownerElement);
  PopupMenu::trace(visitor);
}

void PopupMenuImpl::writeDocument(SharedBuffer* data) {
  HTMLSelectElement& ownerElement = *m_ownerElement;
  IntRect anchorRectInScreen = m_chromeClient->viewportToScreen(
      ownerElement.visibleBoundsInVisualViewport(),
      ownerElement.document().view());

  PagePopupClient::addString(
      "<!DOCTYPE html><head><meta charset='UTF-8'><style>\n", data);
  data->append(Platform::current()->loadResource("pickerCommon.css"));
  data->append(Platform::current()->loadResource("listPicker.css"));
  PagePopupClient::addString(
      "</style></head><body><div id=main>Loading...</div><script>\n"
      "window.dialogArguments = {\n",
      data);
  addProperty("selectedIndex", ownerElement.selectedListIndex(), data);
  const ComputedStyle* ownerStyle = ownerElement.computedStyle();
  ItemIterationContext context(*ownerStyle, data);
  context.serializeBaseStyle();
  PagePopupClient::addString("children: [\n", data);
  const HeapVector<Member<HTMLElement>>& items = ownerElement.listItems();
  for (; context.m_listIndex < items.size(); ++context.m_listIndex) {
    Element& child = *items[context.m_listIndex];
    if (!isHTMLOptGroupElement(child.parentNode()))
      context.finishGroupIfNecessary();
    if (isHTMLOptionElement(child))
      addOption(context, toHTMLOptionElement(child));
    else if (isHTMLOptGroupElement(child))
      addOptGroup(context, toHTMLOptGroupElement(child));
    else if (isHTMLHRElement(child))
      addSeparator(context, toHTMLHRElement(child));
  }
  context.finishGroupIfNecessary();
  PagePopupClient::addString("],\n", data);

  addProperty("anchorRectInScreen", anchorRectInScreen, data);
  float scaleFactor = m_chromeClient->windowToViewportScalar(1.f);
  addProperty("zoomFactor", 1, data);
  addProperty("scaleFactor", scaleFactor, data);
  bool isRTL = !ownerStyle->isLeftToRightDirection();
  addProperty("isRTL", isRTL, data);
  addProperty("paddingStart",
              isRTL ? ownerElement.clientPaddingRight().toDouble()
                    : ownerElement.clientPaddingLeft().toDouble(),
              data);
  PagePopupClient::addString("};\n", data);
  data->append(Platform::current()->loadResource("pickerCommon.js"));
  data->append(Platform::current()->loadResource("listPicker.js"));
  PagePopupClient::addString("</script></body>\n", data);
}

void PopupMenuImpl::addElementStyle(ItemIterationContext& context,
                                    HTMLElement& element) {
  const ComputedStyle* style = m_ownerElement->itemComputedStyle(element);
  DCHECK(style);
  SharedBuffer* data = context.m_buffer;
  // TODO(tkent): We generate unnecessary "style: {\n},\n" even if no
  // additional style.
  PagePopupClient::addString("style: {\n", data);
  if (style->visibility() == EVisibility::kHidden)
    addProperty("visibility", String("hidden"), data);
  if (style->display() == EDisplay::None)
    addProperty("display", String("none"), data);
  const ComputedStyle& baseStyle = context.baseStyle();
  if (baseStyle.direction() != style->direction()) {
    addProperty(
        "direction",
        String(style->direction() == TextDirection::kRtl ? "rtl" : "ltr"),
        data);
  }
  if (isOverride(style->getUnicodeBidi()))
    addProperty("unicodeBidi", String("bidi-override"), data);
  Color foregroundColor = style->visitedDependentColor(CSSPropertyColor);
  if (baseStyle.visitedDependentColor(CSSPropertyColor) != foregroundColor)
    addProperty("color", foregroundColor.serialized(), data);
  Color backgroundColor =
      style->visitedDependentColor(CSSPropertyBackgroundColor);
  if (context.backgroundColor() != backgroundColor &&
      backgroundColor != Color::transparent)
    addProperty("backgroundColor", backgroundColor.serialized(), data);
  const FontDescription& baseFont = context.baseFont();
  const FontDescription& fontDescription = style->font().getFontDescription();
  if (baseFont.computedPixelSize() != fontDescription.computedPixelSize()) {
    // We don't use FontDescription::specifiedSize() because this element
    // might have its own zoom level.
    addProperty("fontSize", fontDescription.computedPixelSize(), data);
  }
  // Our UA stylesheet has font-weight:normal for OPTION.
  if (FontWeightNormal != fontDescription.weight())
    addProperty("fontWeight",
                String(fontWeightToString(fontDescription.weight())), data);
  if (baseFont.family() != fontDescription.family()) {
    PagePopupClient::addString("fontFamily: [\n", data);
    for (const FontFamily* f = &fontDescription.family(); f; f = f->next()) {
      addJavaScriptString(f->family().getString(), data);
      if (f->next())
        PagePopupClient::addString(",\n", data);
    }
    PagePopupClient::addString("],\n", data);
  }
  if (baseFont.style() != fontDescription.style())
    addProperty("fontStyle", String(fontStyleToString(fontDescription.style())),
                data);

  if (baseFont.variantCaps() != fontDescription.variantCaps() &&
      fontDescription.variantCaps() == FontDescription::SmallCaps)
    addProperty("fontVariant", String("small-caps"), data);

  if (baseStyle.textTransform() != style->textTransform())
    addProperty("textTransform",
                String(textTransformToString(style->textTransform())), data);

  PagePopupClient::addString("},\n", data);
}

void PopupMenuImpl::addOption(ItemIterationContext& context,
                              HTMLOptionElement& element) {
  SharedBuffer* data = context.m_buffer;
  PagePopupClient::addString("{", data);
  addProperty("label", element.displayLabel(), data);
  addProperty("value", context.m_listIndex, data);
  if (!element.title().isEmpty())
    addProperty("title", element.title(), data);
  const AtomicString& ariaLabel =
      element.fastGetAttribute(HTMLNames::aria_labelAttr);
  if (!ariaLabel.isEmpty())
    addProperty("ariaLabel", ariaLabel, data);
  if (element.isDisabledFormControl())
    addProperty("disabled", true, data);
  addElementStyle(context, element);
  PagePopupClient::addString("},", data);
}

void PopupMenuImpl::addOptGroup(ItemIterationContext& context,
                                HTMLOptGroupElement& element) {
  SharedBuffer* data = context.m_buffer;
  PagePopupClient::addString("{\n", data);
  PagePopupClient::addString("type: \"optgroup\",\n", data);
  addProperty("label", element.groupLabelText(), data);
  addProperty("title", element.title(), data);
  addProperty("ariaLabel", element.fastGetAttribute(HTMLNames::aria_labelAttr),
              data);
  addProperty("disabled", element.isDisabledFormControl(), data);
  addElementStyle(context, element);
  context.startGroupChildren(*m_ownerElement->itemComputedStyle(element));
  // We should call ItemIterationContext::finishGroupIfNecessary() later.
}

void PopupMenuImpl::addSeparator(ItemIterationContext& context,
                                 HTMLHRElement& element) {
  SharedBuffer* data = context.m_buffer;
  PagePopupClient::addString("{\n", data);
  PagePopupClient::addString("type: \"separator\",\n", data);
  addProperty("title", element.title(), data);
  addProperty("ariaLabel", element.fastGetAttribute(HTMLNames::aria_labelAttr),
              data);
  addProperty("disabled", element.isDisabledFormControl(), data);
  addElementStyle(context, element);
  PagePopupClient::addString("},\n", data);
}

void PopupMenuImpl::selectFontsFromOwnerDocument(Document& document) {
  Document& ownerDocument = ownerElement().document();
  document.styleEngine().setFontSelector(PopupMenuCSSFontSelector::create(
      &document, ownerDocument.styleEngine().fontSelector()));
}

void PopupMenuImpl::setValueAndClosePopup(int numValue,
                                          const String& stringValue) {
  DCHECK(m_popup);
  DCHECK(m_ownerElement);
  if (!stringValue.isEmpty()) {
    bool success;
    int listIndex = stringValue.toInt(&success);
    DCHECK(success);

    EventQueueScope scope;
    m_ownerElement->selectOptionByPopup(listIndex);
    if (m_popup)
      m_chromeClient->closePagePopup(m_popup);
    // 'change' event is dispatched here.  For compatbility with
    // Angular 1.2, we need to dispatch a change event before
    // mouseup/click events.
  } else {
    if (m_popup)
      m_chromeClient->closePagePopup(m_popup);
  }
  // We dispatch events on the owner element to match the legacy behavior.
  // Other browsers dispatch click events before and after showing the popup.
  if (m_ownerElement) {
    PlatformMouseEvent event;
    Element* owner = &ownerElement();
    owner->dispatchMouseEvent(event, EventTypeNames::mouseup);
    owner->dispatchMouseEvent(event, EventTypeNames::click);
  }
}

void PopupMenuImpl::setValue(const String& value) {
  DCHECK(m_ownerElement);
  bool success;
  int listIndex = value.toInt(&success);
  DCHECK(success);
  m_ownerElement->provisionalSelectionChanged(listIndex);
}

void PopupMenuImpl::didClosePopup() {
  // Clearing m_popup first to prevent from trying to close the popup again.
  m_popup = nullptr;
  if (m_ownerElement)
    m_ownerElement->popupDidHide();
}

Element& PopupMenuImpl::ownerElement() {
  return *m_ownerElement;
}

Locale& PopupMenuImpl::locale() {
  return Locale::defaultLocale();
}

void PopupMenuImpl::closePopup() {
  if (m_popup)
    m_chromeClient->closePagePopup(m_popup);
  if (m_ownerElement)
    m_ownerElement->popupDidCancel();
}

void PopupMenuImpl::dispose() {
  if (m_popup)
    m_chromeClient->closePagePopup(m_popup);
}

void PopupMenuImpl::show() {
  DCHECK(!m_popup);
  m_popup = m_chromeClient->openPagePopup(this);
}

void PopupMenuImpl::hide() {
  closePopup();
}

void PopupMenuImpl::updateFromElement(UpdateReason) {
  if (m_needsUpdate)
    return;
  m_needsUpdate = true;
  ownerElement().document().postTask(
      TaskType::UserInteraction, BLINK_FROM_HERE,
      createSameThreadTask(&PopupMenuImpl::update, wrapPersistent(this)));
}

void PopupMenuImpl::update() {
  if (!m_popup || !m_ownerElement)
    return;
  ownerElement().document().updateStyleAndLayoutTree();
  // disconnectClient() might have been called.
  if (!m_ownerElement)
    return;
  m_needsUpdate = false;

  if (!ownerElement()
           .document()
           .frame()
           ->view()
           ->visibleContentRect()
           .intersects(ownerElement().pixelSnappedBoundingBox())) {
    hide();
    return;
  }

  RefPtr<SharedBuffer> data = SharedBuffer::create();
  PagePopupClient::addString("window.updateData = {\n", data.get());
  PagePopupClient::addString("type: \"update\",\n", data.get());
  ItemIterationContext context(*m_ownerElement->computedStyle(), data.get());
  context.serializeBaseStyle();
  PagePopupClient::addString("children: [", data.get());
  const HeapVector<Member<HTMLElement>>& items = m_ownerElement->listItems();
  for (; context.m_listIndex < items.size(); ++context.m_listIndex) {
    Element& child = *items[context.m_listIndex];
    if (!isHTMLOptGroupElement(child.parentNode()))
      context.finishGroupIfNecessary();
    if (isHTMLOptionElement(child))
      addOption(context, toHTMLOptionElement(child));
    else if (isHTMLOptGroupElement(child))
      addOptGroup(context, toHTMLOptGroupElement(child));
    else if (isHTMLHRElement(child))
      addSeparator(context, toHTMLHRElement(child));
  }
  context.finishGroupIfNecessary();
  PagePopupClient::addString("],\n", data.get());
  IntRect anchorRectInScreen = m_chromeClient->viewportToScreen(
      m_ownerElement->visibleBoundsInVisualViewport(),
      ownerElement().document().view());
  addProperty("anchorRectInScreen", anchorRectInScreen, data.get());
  PagePopupClient::addString("}\n", data.get());
  m_popup->postMessage(String::fromUTF8(data->data(), data->size()));
}

void PopupMenuImpl::disconnectClient() {
  m_ownerElement = nullptr;
  // Cannot be done during finalization, so instead done when the
  // layout object is destroyed and disconnected.
  dispose();
}

}  // namespace blink
