// Copyright 2017 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 "core/css/cssom/CSSNumericValue.h"

#include "bindings/core/v8/ExceptionState.h"
#include "core/css/CSSCalculationValue.h"
#include "core/css/CSSPrimitiveValue.h"
#include "core/css/cssom/CSSMathInvert.h"
#include "core/css/cssom/CSSMathMax.h"
#include "core/css/cssom/CSSMathMin.h"
#include "core/css/cssom/CSSMathNegate.h"
#include "core/css/cssom/CSSMathProduct.h"
#include "core/css/cssom/CSSMathSum.h"
#include "core/css/cssom/CSSUnitValue.h"
#include "core/css/parser/CSSParserTokenStream.h"
#include "core/css/parser/CSSTokenizer.h"

#include <numeric>

namespace blink {

namespace {

template <CSSStyleValue::StyleValueType type>
void PrependValueForArithmetic(CSSNumericValueVector& vector,
                               CSSNumericValue* value) {
  DCHECK(value);
  if (value->GetType() == type)
    vector.PrependVector(static_cast<CSSMathVariadic*>(value)->NumericValues());
  else
    vector.push_front(value);
}

template <class BinaryOperation>
CSSUnitValue* MaybeSimplifyAsUnitValue(const CSSNumericValueVector& values,
                                       const BinaryOperation& op) {
  DCHECK(!values.IsEmpty());

  CSSUnitValue* first_unit_value = ToCSSUnitValueOrNull(values[0]);
  if (!first_unit_value)
    return nullptr;

  double final_value = first_unit_value->value();
  for (size_t i = 1; i < values.size(); i++) {
    CSSUnitValue* unit_value = ToCSSUnitValueOrNull(values[i]);
    if (!unit_value ||
        unit_value->GetInternalUnit() != first_unit_value->GetInternalUnit())
      return nullptr;

    final_value = op(final_value, unit_value->value());
  }

  return CSSUnitValue::Create(final_value, first_unit_value->GetInternalUnit());
}

CSSUnitValue* MaybeMultiplyAsUnitValue(const CSSNumericValueVector& values) {
  DCHECK(!values.IsEmpty());

  // We are allowed one unit value with type other than kNumber.
  auto unit_other_than_number = CSSPrimitiveValue::UnitType::kNumber;

  double final_value = 1.0;
  for (size_t i = 0; i < values.size(); i++) {
    CSSUnitValue* unit_value = ToCSSUnitValueOrNull(values[i]);
    if (!unit_value)
      return nullptr;

    if (unit_value->GetInternalUnit() != CSSPrimitiveValue::UnitType::kNumber) {
      if (unit_other_than_number != CSSPrimitiveValue::UnitType::kNumber)
        return nullptr;
      unit_other_than_number = unit_value->GetInternalUnit();
    }

    final_value *= unit_value->value();
  }

  return CSSUnitValue::Create(final_value, unit_other_than_number);
}

CalcOperator CanonicalOperator(CalcOperator op) {
  if (op == kCalcAdd || op == kCalcSubtract)
    return kCalcAdd;
  return kCalcMultiply;
}

bool CanCombineNodes(const CSSCalcExpressionNode& root,
                     const CSSCalcExpressionNode& node) {
  DCHECK_EQ(root.GetType(), CSSCalcExpressionNode::kCssCalcBinaryOperation);
  if (node.GetType() == CSSCalcExpressionNode::kCssCalcPrimitiveValue)
    return false;
  return !node.IsNestedCalc() && CanonicalOperator(root.OperatorType()) ==
                                     CanonicalOperator(node.OperatorType());
}

CSSNumericValue* NegateOrInvertIfRequired(CalcOperator parent_op,
                                          CSSNumericValue* value) {
  DCHECK(value);
  if (parent_op == kCalcSubtract)
    return CSSMathNegate::Create(value);
  if (parent_op == kCalcDivide)
    return CSSMathInvert::Create(value);
  return value;
}

CSSNumericValue* CalcToNumericValue(const CSSCalcExpressionNode& root) {
  if (root.GetType() == CSSCalcExpressionNode::kCssCalcPrimitiveValue) {
    const CSSPrimitiveValue::UnitType unit = root.TypeWithCalcResolved();
    auto* value = CSSUnitValue::Create(
        root.DoubleValue(), unit == CSSPrimitiveValue::UnitType::kInteger
                                ? CSSPrimitiveValue::UnitType::kNumber
                                : unit);
    DCHECK(value);

    // For cases like calc(1), we need to wrap the value in a CSSMathSum
    if (!root.IsNestedCalc())
      return value;

    CSSNumericValueVector values;
    values.push_back(value);
    return CSSMathSum::Create(std::move(values));
  }

  // When the node is a binary operator, we return either a CSSMathSum or a
  // CSSMathProduct.
  DCHECK_EQ(root.GetType(), CSSCalcExpressionNode::kCssCalcBinaryOperation);
  CSSNumericValueVector values;

  // For cases like calc(1 + 2 + 3), the calc expression tree looks like:
  //       +
  //      / \
  //     +   3
  //    / \
  //   1   2
  //
  // But we want to produce a CSSMathValue tree that looks like:
  //       +
  //      /|\
  //     1 2 3
  //
  // So when the left child has the same operator as its parent, we can combine
  // the two nodes. We keep moving down the left side of the tree as long as the
  // current node and the root can be combined, collecting the right child of
  // the nodes that we encounter.
  const CSSCalcExpressionNode* cur_node = &root;
  do {
    DCHECK(cur_node->LeftExpressionNode());
    DCHECK(cur_node->RightExpressionNode());

    const auto& value = CalcToNumericValue(*cur_node->RightExpressionNode());

    // If the current node is a '-' or '/', it's really just a '+' or '*' with
    // the right child negated or inverted, respectively.
    values.push_back(NegateOrInvertIfRequired(cur_node->OperatorType(), value));
    cur_node = cur_node->LeftExpressionNode();
  } while (CanCombineNodes(root, *cur_node));

  DCHECK(cur_node);
  values.push_back(CalcToNumericValue(*cur_node));

  // Our algorithm collects the children in reverse order, so we have to reverse
  // the values.
  std::reverse(values.begin(), values.end());
  if (root.OperatorType() == kCalcAdd || root.OperatorType() == kCalcSubtract)
    return CSSMathSum::Create(std::move(values));
  return CSSMathProduct::Create(std::move(values));
}

CSSUnitValue* CSSNumericSumValueEntryToUnitValue(
    const CSSNumericSumValue::Term& term) {
  if (term.units.size() == 0)
    return CSSUnitValue::Create(term.value);
  if (term.units.size() == 1 && term.units.begin()->value == 1)
    return CSSUnitValue::Create(term.value, term.units.begin()->key);
  return nullptr;
}

}  // namespace

bool CSSNumericValue::IsValidUnit(CSSPrimitiveValue::UnitType unit) {
  // UserUnits returns true for CSSPrimitiveValue::IsLength below.
  if (unit == CSSPrimitiveValue::UnitType::kUserUnits)
    return false;
  if (unit == CSSPrimitiveValue::UnitType::kNumber ||
      unit == CSSPrimitiveValue::UnitType::kPercentage ||
      CSSPrimitiveValue::IsLength(unit) || CSSPrimitiveValue::IsAngle(unit) ||
      CSSPrimitiveValue::IsTime(unit) || CSSPrimitiveValue::IsFrequency(unit) ||
      CSSPrimitiveValue::IsResolution(unit) || CSSPrimitiveValue::IsFlex(unit))
    return true;
  return false;
}

CSSPrimitiveValue::UnitType CSSNumericValue::UnitFromName(const String& name) {
  if (EqualIgnoringASCIICase(name, "number"))
    return CSSPrimitiveValue::UnitType::kNumber;
  if (EqualIgnoringASCIICase(name, "percent") || name == "%")
    return CSSPrimitiveValue::UnitType::kPercentage;
  return CSSPrimitiveValue::StringToUnitType(name);
}

CSSNumericValue* CSSNumericValue::parse(const String& css_text,
                                        ExceptionState& exception_state) {
  CSSTokenizer tokenizer(css_text);
  CSSParserTokenStream stream(tokenizer);
  auto range = stream.ConsumeUntilPeekedTypeIs<>();
  if (!stream.AtEnd()) {
    exception_state.ThrowDOMException(kSyntaxError, "Invalid math expression");
    return nullptr;
  }

  switch (range.Peek().GetType()) {
    case kNumberToken:
    case kPercentageToken:
    case kDimensionToken: {
      const auto token = range.Consume();
      if (!range.AtEnd())
        break;
      return CSSUnitValue::Create(token.NumericValue(), token.GetUnitType());
    }
    case kFunctionToken:
      if (range.Peek().FunctionId() == CSSValueCalc ||
          range.Peek().FunctionId() == CSSValueWebkitCalc) {
        CSSCalcValue* calc_value = CSSCalcValue::Create(range, kValueRangeAll);
        if (!calc_value)
          break;

        DCHECK(calc_value->ExpressionNode());
        return CalcToNumericValue(*calc_value->ExpressionNode());
      }
    default:
      break;
  }

  exception_state.ThrowDOMException(kSyntaxError, "Invalid math expression");
  return nullptr;
}

CSSNumericValue* CSSNumericValue::FromCSSValue(const CSSPrimitiveValue& value) {
  if (value.IsCalculated())
    return CalcToNumericValue(*value.CssCalcValue()->ExpressionNode());
  return CSSUnitValue::FromCSSValue(value);
}

/* static */
CSSNumericValue* CSSNumericValue::FromNumberish(const CSSNumberish& value) {
  if (value.IsDouble()) {
    return CSSUnitValue::Create(value.GetAsDouble(),
                                CSSPrimitiveValue::UnitType::kNumber);
  }
  return value.GetAsCSSNumericValue();
}

CSSUnitValue* CSSNumericValue::to(const String& unit_string,
                                  ExceptionState& exception_state) {
  CSSPrimitiveValue::UnitType target_unit = UnitFromName(unit_string);
  if (!IsValidUnit(target_unit)) {
    exception_state.ThrowDOMException(kSyntaxError,
                                      "Invalid unit for conversion");
    return nullptr;
  }

  CSSUnitValue* result = to(target_unit);
  if (!result) {
    exception_state.ThrowTypeError("Cannot convert to " + unit_string);
    return nullptr;
  }

  return result;
}

CSSUnitValue* CSSNumericValue::to(CSSPrimitiveValue::UnitType unit) const {
  const auto sum = SumValue();
  if (!sum || sum->terms.size() != 1)
    return nullptr;

  CSSUnitValue* value = CSSNumericSumValueEntryToUnitValue(sum->terms[0]);
  if (!value)
    return nullptr;
  return value->ConvertTo(unit);
}

CSSMathSum* CSSNumericValue::toSum(const Vector<String>& unit_strings,
                                   ExceptionState& exception_state) {
  for (const auto& unit_string : unit_strings) {
    if (!IsValidUnit(UnitFromName(unit_string))) {
      exception_state.ThrowDOMException(kSyntaxError,
                                        "Invalid unit for conversion");
      return nullptr;
    }
  }

  const WTF::Optional<CSSNumericSumValue> sum = SumValue();
  if (!sum) {
    exception_state.ThrowTypeError("Invalid value for conversion");
    return nullptr;
  }

  CSSNumericValueVector values;
  for (const auto& term : sum->terms) {
    CSSUnitValue* value = CSSNumericSumValueEntryToUnitValue(term);
    if (!value) {
      exception_state.ThrowTypeError("Invalid value for conversion");
      return nullptr;
    }
    values.push_back(value);
  }

  if (unit_strings.size() == 0) {
    std::sort(values.begin(), values.end(), [](const auto& a, const auto& b) {
      return WTF::CodePointCompareLessThan(ToCSSUnitValue(a)->unit(),
                                           ToCSSUnitValue(b)->unit());
    });

    // We got 'values' from a sum value, so it must be a valid CSSMathSum.
    CSSMathSum* result = CSSMathSum::Create(values);
    DCHECK(result);
    return result;
  }

  CSSNumericValueVector result;
  for (const auto& unit_string : unit_strings) {
    CSSPrimitiveValue::UnitType target_unit = UnitFromName(unit_string);
    DCHECK(IsValidUnit(target_unit));

    // Collect all the terms that are compatible with this unit.
    // We mark used terms as null so we don't use them again.
    double total_value =
        std::accumulate(values.begin(), values.end(), 0.0,
                        [target_unit](double cur_sum, auto& value) {
                          if (value) {
                            auto& unit_value = ToCSSUnitValue(*value);
                            if (const auto* converted_value =
                                    unit_value.ConvertTo(target_unit)) {
                              cur_sum += converted_value->value();
                              value = nullptr;
                            }
                          }
                          return cur_sum;
                        });

    result.push_back(CSSUnitValue::Create(total_value, target_unit));
  }

  if (std::any_of(values.begin(), values.end(),
                  [](const auto& v) { return v; })) {
    exception_state.ThrowTypeError(
        "There were leftover terms that were not converted");
    return nullptr;
  }

  CSSMathSum* value = CSSMathSum::Create(result);
  if (!value) {
    exception_state.ThrowTypeError("Can't create CSSMathSum");
    return nullptr;
  }
  return value;
}

CSSNumericValue* CSSNumericValue::add(
    const HeapVector<CSSNumberish>& numberishes,
    ExceptionState& exception_state) {
  auto values = CSSNumberishesToNumericValues(numberishes);
  PrependValueForArithmetic<kSumType>(values, this);

  if (CSSUnitValue* unit_value =
          MaybeSimplifyAsUnitValue(values, std::plus<double>())) {
    return unit_value;
  }
  return CSSMathSum::Create(std::move(values));
}

CSSNumericValue* CSSNumericValue::sub(
    const HeapVector<CSSNumberish>& numberishes,
    ExceptionState& exception_state) {
  auto values = CSSNumberishesToNumericValues(numberishes);
  std::transform(values.begin(), values.end(), values.begin(),
                 [](CSSNumericValue* v) { return v->Negate(); });
  PrependValueForArithmetic<kSumType>(values, this);

  if (CSSUnitValue* unit_value =
          MaybeSimplifyAsUnitValue(values, std::plus<double>())) {
    return unit_value;
  }
  return CSSMathSum::Create(std::move(values));
}

CSSNumericValue* CSSNumericValue::mul(
    const HeapVector<CSSNumberish>& numberishes,
    ExceptionState& exception_state) {
  auto values = CSSNumberishesToNumericValues(numberishes);
  PrependValueForArithmetic<kProductType>(values, this);

  if (CSSUnitValue* unit_value = MaybeMultiplyAsUnitValue(values))
    return unit_value;
  return CSSMathProduct::Create(std::move(values));
}

CSSNumericValue* CSSNumericValue::div(
    const HeapVector<CSSNumberish>& numberishes,
    ExceptionState& exception_state) {
  auto values = CSSNumberishesToNumericValues(numberishes);
  std::transform(values.begin(), values.end(), values.begin(),
                 [](CSSNumericValue* v) { return v->Invert(); });
  PrependValueForArithmetic<kProductType>(values, this);

  if (CSSUnitValue* unit_value = MaybeMultiplyAsUnitValue(values))
    return unit_value;
  return CSSMathProduct::Create(std::move(values));
}

CSSNumericValue* CSSNumericValue::min(
    const HeapVector<CSSNumberish>& numberishes,
    ExceptionState& exception_state) {
  auto values = CSSNumberishesToNumericValues(numberishes);
  PrependValueForArithmetic<kMinType>(values, this);

  if (CSSUnitValue* unit_value = MaybeSimplifyAsUnitValue(
          values, [](double a, double b) { return std::min(a, b); })) {
    return unit_value;
  }
  return CSSMathMin::Create(std::move(values));
}

CSSNumericValue* CSSNumericValue::max(
    const HeapVector<CSSNumberish>& numberishes,
    ExceptionState& exception_state) {
  auto values = CSSNumberishesToNumericValues(numberishes);
  PrependValueForArithmetic<kMaxType>(values, this);

  if (CSSUnitValue* unit_value = MaybeSimplifyAsUnitValue(
          values, [](double a, double b) { return std::max(a, b); })) {
    return unit_value;
  }
  return CSSMathMax::Create(std::move(values));
}

bool CSSNumericValue::equals(const HeapVector<CSSNumberish>& args) {
  CSSNumericValueVector values = CSSNumberishesToNumericValues(args);
  return std::all_of(values.begin(), values.end(),
                     [this](const auto& v) { return this->Equals(*v); });
}

CSSNumericValue* CSSNumericValue::Negate() {
  return CSSMathNegate::Create(this);
}

CSSNumericValue* CSSNumericValue::Invert() {
  return CSSMathInvert::Create(this);
}

CSSNumericValueVector CSSNumberishesToNumericValues(
    const HeapVector<CSSNumberish>& values) {
  CSSNumericValueVector result;
  for (const CSSNumberish& value : values) {
    result.push_back(CSSNumericValue::FromNumberish(value));
  }
  return result;
}

}  // namespace blink
