// 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/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::Capitalize:
      return "capitalize";
    case ETextTransform::Uppercase:
      return "uppercase";
    case ETextTransform::Lowercase:
      return "lowercase";
    case ETextTransform::None:
      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().specifiedSize(), 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 zoom = zoomFactor();
  float scaleFactor = m_chromeClient->windowToViewportScalar(1.f);
  addProperty("zoomFactor", zoom / scaleFactor, data);
  bool isRTL = !ownerStyle->isLeftToRightDirection();
  addProperty("isRTL", isRTL, data);
  addProperty("paddingStart",
              isRTL ? ownerElement.clientPaddingRight().toDouble() / zoom
                    : ownerElement.clientPaddingLeft().toDouble() / zoom,
              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::Hidden)
    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() == RTL ? "rtl" : "ltr"),
                data);
  if (isOverride(style->unicodeBidi()))
    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.computedSize() / zoomFactor(),
                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() {
  if (m_popup)
    m_chromeClient->closePagePopup(m_popup);
}

void PopupMenuImpl::updateFromElement(UpdateReason) {
  if (m_needsUpdate)
    return;
  m_needsUpdate = true;
  ownerElement().document().postTask(
      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
