/*
 * CSS Media Query Evaluator
 *
 * Copyright (C) 2006 Kimmo Kinnunen <kimmo.t.kinnunen@nokia.com>.
 * Copyright (C) 2013 Apple Inc. All rights reserved.
 * Copyright (C) 2013 Intel Corporation. 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 THE AUTHOR ``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 "core/css/MediaQueryEvaluator.h"

#include "core/CSSValueKeywords.h"
#include "core/MediaFeatureNames.h"
#include "core/MediaFeatures.h"
#include "core/MediaTypeNames.h"
#include "core/css/CSSHelper.h"
#include "core/css/CSSPrimitiveValue.h"
#include "core/css/CSSToLengthConversionData.h"
#include "core/css/MediaList.h"
#include "core/css/MediaQuery.h"
#include "core/css/MediaValuesDynamic.h"
#include "core/css/MediaValuesInitialViewport.h"
#include "core/css/resolver/MediaQueryResult.h"
#include "core/dom/NodeComputedStyle.h"
#include "core/frame/FrameHost.h"
#include "core/frame/FrameView.h"
#include "core/frame/LocalFrame.h"
#include "core/frame/Settings.h"
#include "core/frame/UseCounter.h"
#include "core/inspector/InspectorInstrumentation.h"
#include "core/style/ComputedStyle.h"
#include "platform/RuntimeEnabledFeatures.h"
#include "platform/geometry/FloatRect.h"
#include "platform/graphics/ColorSpace.h"
#include "public/platform/PointerProperties.h"
#include "public/platform/ShapeProperties.h"
#include "public/platform/WebDisplayMode.h"
#include "wtf/HashMap.h"

namespace blink {

using namespace MediaFeatureNames;

enum MediaFeaturePrefix { MinPrefix, MaxPrefix, NoPrefix };

using EvalFunc = bool (*)(const MediaQueryExpValue&,
                          MediaFeaturePrefix,
                          const MediaValues&);
using FunctionMap = HashMap<StringImpl*, EvalFunc>;
static FunctionMap* gFunctionMap;

MediaQueryEvaluator::MediaQueryEvaluator(const char* acceptedMediaType)
    : m_mediaType(acceptedMediaType) {}

MediaQueryEvaluator::MediaQueryEvaluator(LocalFrame* frame)
    : m_mediaValues(MediaValues::createDynamicIfFrameExists(frame)) {}

MediaQueryEvaluator::MediaQueryEvaluator(const MediaValues& mediaValues)
    : m_mediaValues(mediaValues.copy()) {}

MediaQueryEvaluator::MediaQueryEvaluator(
    MediaValuesInitialViewport* mediaValues)
    : m_mediaValues(mediaValues) {
  DCHECK(mediaValues);
}

MediaQueryEvaluator::~MediaQueryEvaluator() {}

DEFINE_TRACE(MediaQueryEvaluator) {
  visitor->trace(m_mediaValues);
}

const String MediaQueryEvaluator::mediaType() const {
  // If a static mediaType was given by the constructor, we use it here.
  if (!m_mediaType.isEmpty())
    return m_mediaType;
  // Otherwise, we get one from mediaValues (which may be dynamic or cached).
  if (m_mediaValues)
    return m_mediaValues->mediaType();
  return nullAtom;
}

bool MediaQueryEvaluator::mediaTypeMatch(const String& mediaTypeToMatch) const {
  return mediaTypeToMatch.isEmpty() ||
         equalIgnoringCase(mediaTypeToMatch, MediaTypeNames::all) ||
         equalIgnoringCase(mediaTypeToMatch, mediaType());
}

static bool applyRestrictor(MediaQuery::RestrictorType r, bool value) {
  return r == MediaQuery::Not ? !value : value;
}

bool MediaQueryEvaluator::eval(
    const MediaQuery* query,
    MediaQueryResultList* viewportDependentMediaQueryResults,
    MediaQueryResultList* deviceDependentMediaQueryResults) const {
  if (!mediaTypeMatch(query->mediaType()))
    return applyRestrictor(query->restrictor(), false);

  const ExpressionHeapVector& expressions = query->expressions();
  // Iterate through expressions, stop if any of them eval to false (AND
  // semantics).
  size_t i = 0;
  for (; i < expressions.size(); ++i) {
    bool exprResult = eval(expressions.at(i).get());
    if (viewportDependentMediaQueryResults &&
        expressions.at(i)->isViewportDependent())
      viewportDependentMediaQueryResults->push_back(
          new MediaQueryResult(*expressions.at(i), exprResult));
    if (deviceDependentMediaQueryResults &&
        expressions.at(i)->isDeviceDependent())
      deviceDependentMediaQueryResults->push_back(
          new MediaQueryResult(*expressions.at(i), exprResult));
    if (!exprResult)
      break;
  }

  // Assume true if we are at the end of the list, otherwise assume false.
  return applyRestrictor(query->restrictor(), expressions.size() == i);
}

bool MediaQueryEvaluator::eval(
    const MediaQuerySet* querySet,
    MediaQueryResultList* viewportDependentMediaQueryResults,
    MediaQueryResultList* deviceDependentMediaQueryResults) const {
  if (!querySet)
    return true;

  const HeapVector<Member<MediaQuery>>& queries = querySet->queryVector();
  if (!queries.size())
    return true;  // Empty query list evaluates to true.

  // Iterate over queries, stop if any of them eval to true (OR semantics).
  bool result = false;
  for (size_t i = 0; i < queries.size() && !result; ++i)
    result = eval(queries[i].get(), viewportDependentMediaQueryResults,
                  deviceDependentMediaQueryResults);

  return result;
}

template <typename T>
bool compareValue(T a, T b, MediaFeaturePrefix op) {
  switch (op) {
    case MinPrefix:
      return a >= b;
    case MaxPrefix:
      return a <= b;
    case NoPrefix:
      return a == b;
  }
  return false;
}

bool compareDoubleValue(double a, double b, MediaFeaturePrefix op) {
  const double precision = std::numeric_limits<double>::epsilon();
  switch (op) {
    case MinPrefix:
      return a >= (b - precision);
    case MaxPrefix:
      return a <= (b + precision);
    case NoPrefix:
      return std::abs(a - b) <= precision;
  }
  return false;
}

static bool compareAspectRatioValue(const MediaQueryExpValue& value,
                                    int width,
                                    int height,
                                    MediaFeaturePrefix op) {
  if (value.isRatio)
    return compareValue(width * static_cast<int>(value.denominator),
                        height * static_cast<int>(value.numerator), op);

  return false;
}

static bool numberValue(const MediaQueryExpValue& value, float& result) {
  if (value.isValue && value.unit == CSSPrimitiveValue::UnitType::Number) {
    result = value.value;
    return true;
  }
  return false;
}

static bool colorMediaFeatureEval(const MediaQueryExpValue& value,
                                  MediaFeaturePrefix op,
                                  const MediaValues& mediaValues) {
  float number;
  int bitsPerComponent = mediaValues.colorBitsPerComponent();
  if (value.isValid())
    return numberValue(value, number) &&
           compareValue(bitsPerComponent, static_cast<int>(number), op);

  return bitsPerComponent != 0;
}

static bool colorIndexMediaFeatureEval(const MediaQueryExpValue& value,
                                       MediaFeaturePrefix op,
                                       const MediaValues&) {
  // FIXME: We currently assume that we do not support indexed displays, as it
  // is unknown how to retrieve the information if the display mode is indexed.
  // This matches Firefox.
  if (!value.isValid())
    return false;

  // Acording to spec, if the device does not use a color lookup table, the
  // value is zero.
  float number;
  return numberValue(value, number) &&
         compareValue(0, static_cast<int>(number), op);
}

static bool monochromeMediaFeatureEval(const MediaQueryExpValue& value,
                                       MediaFeaturePrefix op,
                                       const MediaValues& mediaValues) {
  if (!mediaValues.monochromeBitsPerComponent()) {
    if (value.isValid()) {
      float number;
      return numberValue(value, number) &&
             compareValue(0, static_cast<int>(number), op);
    }
    return false;
  }

  return colorMediaFeatureEval(value, op, mediaValues);
}

static bool displayModeMediaFeatureEval(const MediaQueryExpValue& value,
                                        MediaFeaturePrefix,
                                        const MediaValues& mediaValues) {
  // isValid() is false if there is no parameter. Without parameter we should
  // return true to indicate that displayModeMediaFeature is enabled in the
  // browser.
  if (!value.isValid())
    return true;

  if (!value.isID)
    return false;

  WebDisplayMode mode = mediaValues.displayMode();
  switch (value.id) {
    case CSSValueFullscreen:
      return mode == WebDisplayModeFullscreen;
    case CSSValueStandalone:
      return mode == WebDisplayModeStandalone;
    case CSSValueMinimalUi:
      return mode == WebDisplayModeMinimalUi;
    case CSSValueBrowser:
      return mode == WebDisplayModeBrowser;
    default:
      ASSERT_NOT_REACHED();
      return false;
  }
}

static bool orientationMediaFeatureEval(const MediaQueryExpValue& value,
                                        MediaFeaturePrefix,
                                        const MediaValues& mediaValues) {
  int width = mediaValues.viewportWidth();
  int height = mediaValues.viewportHeight();

  if (value.isID) {
    if (width > height)  // Square viewport is portrait.
      return CSSValueLandscape == value.id;
    return CSSValuePortrait == value.id;
  }

  // Expression (orientation) evaluates to true if width and height >= 0.
  return height >= 0 && width >= 0;
}

static bool aspectRatioMediaFeatureEval(const MediaQueryExpValue& value,
                                        MediaFeaturePrefix op,
                                        const MediaValues& mediaValues) {
  if (value.isValid())
    return compareAspectRatioValue(value, mediaValues.viewportWidth(),
                                   mediaValues.viewportHeight(), op);

  // ({,min-,max-}aspect-ratio)
  // assume if we have a device, its aspect ratio is non-zero.
  return true;
}

static bool deviceAspectRatioMediaFeatureEval(const MediaQueryExpValue& value,
                                              MediaFeaturePrefix op,
                                              const MediaValues& mediaValues) {
  if (value.isValid())
    return compareAspectRatioValue(value, mediaValues.deviceWidth(),
                                   mediaValues.deviceHeight(), op);

  // ({,min-,max-}device-aspect-ratio)
  // assume if we have a device, its aspect ratio is non-zero.
  return true;
}

static bool evalResolution(const MediaQueryExpValue& value,
                           MediaFeaturePrefix op,
                           const MediaValues& mediaValues) {
  // According to MQ4, only 'screen', 'print' and 'speech' may match.
  // FIXME: What should speech match?
  // https://www.w3.org/Style/CSS/Tracker/issues/348
  float actualResolution = 0;

  // This checks the actual media type applied to the document, and we know
  // this method only got called if this media type matches the one defined
  // in the query. Thus, if if the document's media type is "print", the
  // media type of the query will either be "print" or "all".
  if (equalIgnoringCase(mediaValues.mediaType(), MediaTypeNames::screen)) {
    actualResolution = clampTo<float>(mediaValues.devicePixelRatio());
  } else if (equalIgnoringCase(mediaValues.mediaType(),
                               MediaTypeNames::print)) {
    // The resolution of images while printing should not depend on the DPI
    // of the screen. Until we support proper ways of querying this info
    // we use 300px which is considered minimum for current printers.
    actualResolution = 300 / cssPixelsPerInch;
  }

  if (!value.isValid())
    return !!actualResolution;

  if (!value.isValue)
    return false;

  if (value.unit == CSSPrimitiveValue::UnitType::Number)
    return compareValue(actualResolution, clampTo<float>(value.value), op);

  if (!CSSPrimitiveValue::isResolution(value.unit))
    return false;

  double canonicalFactor =
      CSSPrimitiveValue::conversionToCanonicalUnitsScaleFactor(value.unit);
  double dppxFactor = CSSPrimitiveValue::conversionToCanonicalUnitsScaleFactor(
      CSSPrimitiveValue::UnitType::DotsPerPixel);
  float valueInDppx =
      clampTo<float>(value.value * (canonicalFactor / dppxFactor));
  if (value.unit == CSSPrimitiveValue::UnitType::DotsPerCentimeter) {
    // To match DPCM to DPPX values, we limit to 2 decimal points.
    // The http://dev.w3.org/csswg/css3-values/#absolute-lengths recommends
    // "that the pixel unit refer to the whole number of device pixels that best
    // approximates the reference pixel". With that in mind, allowing 2 decimal
    // point precision seems appropriate.
    return compareValue(floorf(0.5 + 100 * actualResolution) / 100,
                        floorf(0.5 + 100 * valueInDppx) / 100, op);
  }

  return compareValue(actualResolution, valueInDppx, op);
}

static bool devicePixelRatioMediaFeatureEval(const MediaQueryExpValue& value,
                                             MediaFeaturePrefix op,
                                             const MediaValues& mediaValues) {
  UseCounter::count(mediaValues.document(),
                    UseCounter::PrefixedDevicePixelRatioMediaFeature);

  return (!value.isValid() ||
          value.unit == CSSPrimitiveValue::UnitType::Number) &&
         evalResolution(value, op, mediaValues);
}

static bool resolutionMediaFeatureEval(const MediaQueryExpValue& value,
                                       MediaFeaturePrefix op,
                                       const MediaValues& MediaValues) {
  return (!value.isValid() || CSSPrimitiveValue::isResolution(value.unit)) &&
         evalResolution(value, op, MediaValues);
}

static bool gridMediaFeatureEval(const MediaQueryExpValue& value,
                                 MediaFeaturePrefix op,
                                 const MediaValues&) {
  // if output device is bitmap, grid: 0 == true
  // assume we have bitmap device
  float number;
  if (value.isValid() && numberValue(value, number))
    return compareValue(static_cast<int>(number), 0, op);
  return false;
}

static bool computeLength(const MediaQueryExpValue& value,
                          const MediaValues& mediaValues,
                          double& result) {
  if (!value.isValue)
    return false;

  if (value.unit == CSSPrimitiveValue::UnitType::Number) {
    result = clampTo<int>(value.value);
    return !mediaValues.strictMode() || !result;
  }

  if (CSSPrimitiveValue::isLength(value.unit))
    return mediaValues.computeLength(value.value, value.unit, result);
  return false;
}

static bool computeLengthAndCompare(const MediaQueryExpValue& value,
                                    MediaFeaturePrefix op,
                                    const MediaValues& mediaValues,
                                    double compareToValue) {
  double length;
  return computeLength(value, mediaValues, length) &&
         compareDoubleValue(compareToValue, length, op);
}

static bool deviceHeightMediaFeatureEval(const MediaQueryExpValue& value,
                                         MediaFeaturePrefix op,
                                         const MediaValues& mediaValues) {
  if (value.isValid())
    return computeLengthAndCompare(value, op, mediaValues,
                                   mediaValues.deviceHeight());

  // ({,min-,max-}device-height)
  // assume if we have a device, assume non-zero
  return true;
}

static bool deviceWidthMediaFeatureEval(const MediaQueryExpValue& value,
                                        MediaFeaturePrefix op,
                                        const MediaValues& mediaValues) {
  if (value.isValid())
    return computeLengthAndCompare(value, op, mediaValues,
                                   mediaValues.deviceWidth());

  // ({,min-,max-}device-width)
  // assume if we have a device, assume non-zero
  return true;
}

static bool heightMediaFeatureEval(const MediaQueryExpValue& value,
                                   MediaFeaturePrefix op,
                                   const MediaValues& mediaValues) {
  double height = mediaValues.viewportHeight();
  if (value.isValid())
    return computeLengthAndCompare(value, op, mediaValues, height);

  return height;
}

static bool widthMediaFeatureEval(const MediaQueryExpValue& value,
                                  MediaFeaturePrefix op,
                                  const MediaValues& mediaValues) {
  double width = mediaValues.viewportWidth();
  if (value.isValid())
    return computeLengthAndCompare(value, op, mediaValues, width);

  return width;
}

// Rest of the functions are trampolines which set the prefix according to the
// media feature expression used.

static bool minColorMediaFeatureEval(const MediaQueryExpValue& value,
                                     MediaFeaturePrefix,
                                     const MediaValues& mediaValues) {
  return colorMediaFeatureEval(value, MinPrefix, mediaValues);
}

static bool maxColorMediaFeatureEval(const MediaQueryExpValue& value,
                                     MediaFeaturePrefix,
                                     const MediaValues& mediaValues) {
  return colorMediaFeatureEval(value, MaxPrefix, mediaValues);
}

static bool minColorIndexMediaFeatureEval(const MediaQueryExpValue& value,
                                          MediaFeaturePrefix,
                                          const MediaValues& mediaValues) {
  return colorIndexMediaFeatureEval(value, MinPrefix, mediaValues);
}

static bool maxColorIndexMediaFeatureEval(const MediaQueryExpValue& value,
                                          MediaFeaturePrefix,
                                          const MediaValues& mediaValues) {
  return colorIndexMediaFeatureEval(value, MaxPrefix, mediaValues);
}

static bool minMonochromeMediaFeatureEval(const MediaQueryExpValue& value,
                                          MediaFeaturePrefix,
                                          const MediaValues& mediaValues) {
  return monochromeMediaFeatureEval(value, MinPrefix, mediaValues);
}

static bool maxMonochromeMediaFeatureEval(const MediaQueryExpValue& value,
                                          MediaFeaturePrefix,
                                          const MediaValues& mediaValues) {
  return monochromeMediaFeatureEval(value, MaxPrefix, mediaValues);
}

static bool minAspectRatioMediaFeatureEval(const MediaQueryExpValue& value,
                                           MediaFeaturePrefix,
                                           const MediaValues& mediaValues) {
  return aspectRatioMediaFeatureEval(value, MinPrefix, mediaValues);
}

static bool maxAspectRatioMediaFeatureEval(const MediaQueryExpValue& value,
                                           MediaFeaturePrefix,
                                           const MediaValues& mediaValues) {
  return aspectRatioMediaFeatureEval(value, MaxPrefix, mediaValues);
}

static bool minDeviceAspectRatioMediaFeatureEval(
    const MediaQueryExpValue& value,
    MediaFeaturePrefix,
    const MediaValues& mediaValues) {
  return deviceAspectRatioMediaFeatureEval(value, MinPrefix, mediaValues);
}

static bool maxDeviceAspectRatioMediaFeatureEval(
    const MediaQueryExpValue& value,
    MediaFeaturePrefix,
    const MediaValues& mediaValues) {
  return deviceAspectRatioMediaFeatureEval(value, MaxPrefix, mediaValues);
}

static bool minDevicePixelRatioMediaFeatureEval(
    const MediaQueryExpValue& value,
    MediaFeaturePrefix,
    const MediaValues& mediaValues) {
  UseCounter::count(mediaValues.document(),
                    UseCounter::PrefixedMinDevicePixelRatioMediaFeature);

  return devicePixelRatioMediaFeatureEval(value, MinPrefix, mediaValues);
}

static bool maxDevicePixelRatioMediaFeatureEval(
    const MediaQueryExpValue& value,
    MediaFeaturePrefix,
    const MediaValues& mediaValues) {
  UseCounter::count(mediaValues.document(),
                    UseCounter::PrefixedMaxDevicePixelRatioMediaFeature);

  return devicePixelRatioMediaFeatureEval(value, MaxPrefix, mediaValues);
}

static bool minHeightMediaFeatureEval(const MediaQueryExpValue& value,
                                      MediaFeaturePrefix,
                                      const MediaValues& mediaValues) {
  return heightMediaFeatureEval(value, MinPrefix, mediaValues);
}

static bool maxHeightMediaFeatureEval(const MediaQueryExpValue& value,
                                      MediaFeaturePrefix,
                                      const MediaValues& mediaValues) {
  return heightMediaFeatureEval(value, MaxPrefix, mediaValues);
}

static bool minWidthMediaFeatureEval(const MediaQueryExpValue& value,
                                     MediaFeaturePrefix,
                                     const MediaValues& mediaValues) {
  return widthMediaFeatureEval(value, MinPrefix, mediaValues);
}

static bool maxWidthMediaFeatureEval(const MediaQueryExpValue& value,
                                     MediaFeaturePrefix,
                                     const MediaValues& mediaValues) {
  return widthMediaFeatureEval(value, MaxPrefix, mediaValues);
}

static bool minDeviceHeightMediaFeatureEval(const MediaQueryExpValue& value,
                                            MediaFeaturePrefix,
                                            const MediaValues& mediaValues) {
  return deviceHeightMediaFeatureEval(value, MinPrefix, mediaValues);
}

static bool maxDeviceHeightMediaFeatureEval(const MediaQueryExpValue& value,
                                            MediaFeaturePrefix,
                                            const MediaValues& mediaValues) {
  return deviceHeightMediaFeatureEval(value, MaxPrefix, mediaValues);
}

static bool minDeviceWidthMediaFeatureEval(const MediaQueryExpValue& value,
                                           MediaFeaturePrefix,
                                           const MediaValues& mediaValues) {
  return deviceWidthMediaFeatureEval(value, MinPrefix, mediaValues);
}

static bool maxDeviceWidthMediaFeatureEval(const MediaQueryExpValue& value,
                                           MediaFeaturePrefix,
                                           const MediaValues& mediaValues) {
  return deviceWidthMediaFeatureEval(value, MaxPrefix, mediaValues);
}

static bool minResolutionMediaFeatureEval(const MediaQueryExpValue& value,
                                          MediaFeaturePrefix,
                                          const MediaValues& mediaValues) {
  return resolutionMediaFeatureEval(value, MinPrefix, mediaValues);
}

static bool maxResolutionMediaFeatureEval(const MediaQueryExpValue& value,
                                          MediaFeaturePrefix,
                                          const MediaValues& mediaValues) {
  return resolutionMediaFeatureEval(value, MaxPrefix, mediaValues);
}

static bool transform3dMediaFeatureEval(const MediaQueryExpValue& value,
                                        MediaFeaturePrefix op,
                                        const MediaValues& mediaValues) {
  UseCounter::count(mediaValues.document(),
                    UseCounter::PrefixedTransform3dMediaFeature);

  bool returnValueIfNoParameter;
  int have3dRendering;

  bool threeDEnabled = mediaValues.threeDEnabled();

  returnValueIfNoParameter = threeDEnabled;
  have3dRendering = threeDEnabled ? 1 : 0;

  if (value.isValid()) {
    float number;
    return numberValue(value, number) &&
           compareValue(have3dRendering, static_cast<int>(number), op);
  }
  return returnValueIfNoParameter;
}

static bool hoverMediaFeatureEval(const MediaQueryExpValue& value,
                                  MediaFeaturePrefix,
                                  const MediaValues& mediaValues) {
  HoverType hover = mediaValues.primaryHoverType();

  if (!value.isValid())
    return hover != HoverTypeNone;

  if (!value.isID)
    return false;

  return (hover == HoverTypeNone && value.id == CSSValueNone) ||
         (hover == HoverTypeHover && value.id == CSSValueHover);
}

static bool anyHoverMediaFeatureEval(const MediaQueryExpValue& value,
                                     MediaFeaturePrefix,
                                     const MediaValues& mediaValues) {
  int availableHoverTypes = mediaValues.availableHoverTypes();

  if (!value.isValid())
    return availableHoverTypes & ~HoverTypeNone;

  if (!value.isID)
    return false;

  switch (value.id) {
    case CSSValueNone:
      return availableHoverTypes & HoverTypeNone;
    case CSSValueHover:
      return availableHoverTypes & HoverTypeHover;
    default:
      ASSERT_NOT_REACHED();
      return false;
  }
}

static bool pointerMediaFeatureEval(const MediaQueryExpValue& value,
                                    MediaFeaturePrefix,
                                    const MediaValues& mediaValues) {
  PointerType pointer = mediaValues.primaryPointerType();

  if (!value.isValid())
    return pointer != PointerTypeNone;

  if (!value.isID)
    return false;

  return (pointer == PointerTypeNone && value.id == CSSValueNone) ||
         (pointer == PointerTypeCoarse && value.id == CSSValueCoarse) ||
         (pointer == PointerTypeFine && value.id == CSSValueFine);
}

static bool shapeMediaFeatureEval(const MediaQueryExpValue& value,
                                  MediaFeaturePrefix,
                                  const MediaValues& mediaValues) {
  if (!value.isValid())
    return true;

  if (!value.isID)
    return false;

  DisplayShape shape = mediaValues.displayShape();

  switch (value.id) {
    case CSSValueRect:
      return shape == DisplayShapeRect;
    case CSSValueRound:
      return shape == DisplayShapeRound;
    default:
      NOTREACHED();
      return false;
  }
}

static bool anyPointerMediaFeatureEval(const MediaQueryExpValue& value,
                                       MediaFeaturePrefix,
                                       const MediaValues& mediaValues) {
  int availablePointers = mediaValues.availablePointerTypes();

  if (!value.isValid())
    return availablePointers & ~PointerTypeNone;

  if (!value.isID)
    return false;

  switch (value.id) {
    case CSSValueCoarse:
      return availablePointers & PointerTypeCoarse;
    case CSSValueFine:
      return availablePointers & PointerTypeFine;
    case CSSValueNone:
      return availablePointers & PointerTypeNone;
    default:
      ASSERT_NOT_REACHED();
      return false;
  }
}

static bool scanMediaFeatureEval(const MediaQueryExpValue& value,
                                 MediaFeaturePrefix,
                                 const MediaValues& mediaValues) {
  // Scan only applies to 'tv' media.
  if (!equalIgnoringCase(mediaValues.mediaType(), MediaTypeNames::tv))
    return false;

  if (!value.isValid())
    return true;

  if (!value.isID)
    return false;

  // If a platform interface supplies progressive/interlace info for TVs in the
  // future, it needs to be handled here. For now, assume a modern TV with
  // progressive display.
  return (value.id == CSSValueProgressive);
}

static bool colorGamutMediaFeatureEval(const MediaQueryExpValue& value,
                                       MediaFeaturePrefix,
                                       const MediaValues& mediaValues) {
  // isValid() is false if there is no parameter. Without parameter we should
  // return true to indicate that colorGamutMediaFeature is enabled in the
  // browser.
  if (!value.isValid())
    return true;

  if (!value.isID)
    return false;

  DCHECK(value.id == CSSValueSRGB || value.id == CSSValueP3 ||
         value.id == CSSValueRec2020);

  ColorSpaceGamut gamut = mediaValues.colorGamut();
  switch (gamut) {
    case ColorSpaceGamut::Unknown:
    case ColorSpaceGamut::LessThanNTSC:
    case ColorSpaceGamut::NTSC:
    case ColorSpaceGamut::SRGB:
      return value.id == CSSValueSRGB;
    case ColorSpaceGamut::AlmostP3:
    case ColorSpaceGamut::P3:
    case ColorSpaceGamut::AdobeRGB:
    case ColorSpaceGamut::Wide:
      return value.id == CSSValueSRGB || value.id == CSSValueP3;
    case ColorSpaceGamut::BT2020:
    case ColorSpaceGamut::ProPhoto:
    case ColorSpaceGamut::UltraWide:
      return value.id == CSSValueSRGB || value.id == CSSValueP3 ||
             value.id == CSSValueRec2020;
    case ColorSpaceGamut::End:
      NOTREACHED();
      return false;
  }

  // This is for some compilers that do not understand that it can't be reached.
  NOTREACHED();
  return false;
}

void MediaQueryEvaluator::init() {
  // Create the table.
  gFunctionMap = new FunctionMap;
#define ADD_TO_FUNCTIONMAP(name) \
  gFunctionMap->set(name##MediaFeature.impl(), name##MediaFeatureEval);
  CSS_MEDIAQUERY_NAMES_FOR_EACH_MEDIAFEATURE(ADD_TO_FUNCTIONMAP);
#undef ADD_TO_FUNCTIONMAP
}

bool MediaQueryEvaluator::eval(const MediaQueryExp* expr) const {
  if (!m_mediaValues || !m_mediaValues->hasValues())
    return true;

  DCHECK(gFunctionMap);

  // Call the media feature evaluation function. Assume no prefix and let
  // trampoline functions override the prefix if prefix is used.
  EvalFunc func = gFunctionMap->at(expr->mediaFeature().impl());
  if (func)
    return func(expr->expValue(), NoPrefix, *m_mediaValues);

  return false;
}

}  // namespace blink
