// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

#ifndef LIBTEXTCLASSIFIER_UTILS_GRAMMAR_SEMANTICS_EVALUATORS_PARSE_NUMBER_EVAL_H_
#define LIBTEXTCLASSIFIER_UTILS_GRAMMAR_SEMANTICS_EVALUATORS_PARSE_NUMBER_EVAL_H_

#include <string>

#include "utils/base/arena.h"
#include "utils/base/statusor.h"
#include "utils/grammar/semantics/eval-context.h"
#include "utils/grammar/semantics/evaluator.h"
#include "utils/grammar/semantics/expression_generated.h"
#include "utils/grammar/semantics/value.h"
#include "utils/strings/numbers.h"

namespace libtextclassifier3::grammar {

// Parses a string as a number.
class ParseNumberEvaluator : public SemanticExpressionEvaluator {
 public:
  explicit ParseNumberEvaluator(const SemanticExpressionEvaluator* composer)
      : composer_(composer) {}

  StatusOr<const SemanticValue*> Apply(const EvalContext& context,
                                       const SemanticExpression* expression,
                                       UnsafeArena* arena) const override {
    TC3_DCHECK_EQ(expression->expression_type(),
                  SemanticExpression_::Expression_ParseNumberExpression);
    const ParseNumberExpression* parse_number_expression =
        expression->expression_as_ParseNumberExpression();

    // Evaluate argument.
    TC3_ASSIGN_OR_RETURN(
        const SemanticValue* value,
        composer_->Apply(context, parse_number_expression->value(), arena));
    if (value == nullptr) {
      return nullptr;
    }
    if (!value->Has<StringPiece>()) {
      return Status(StatusCode::INVALID_ARGUMENT,
                    "Argument didn't evaluate as a string value.");
    }
    const std::string data = value->Value<std::string>();

    // Parse the string data as a number.
    const reflection::BaseType type =
        static_cast<reflection::BaseType>(parse_number_expression->base_type());
    if (flatbuffers::IsLong(type)) {
      TC3_ASSIGN_OR_RETURN(const int64 value, TryParse<int64>(data));
      return SemanticValue::Create(type, value, arena);
    } else if (flatbuffers::IsInteger(type)) {
      TC3_ASSIGN_OR_RETURN(const int32 value, TryParse<int32>(data));
      return SemanticValue::Create(type, value, arena);
    } else if (flatbuffers::IsFloat(type)) {
      TC3_ASSIGN_OR_RETURN(const double value, TryParse<double>(data));
      return SemanticValue::Create(type, value, arena);
    } else {
      return Status(StatusCode::INVALID_ARGUMENT,
                    "Unsupported type: " + std::to_string(type));
    }
  }

 private:
  template <typename T>
  bool Parse(const std::string& data, T* value) const;

  template <>
  bool Parse(const std::string& data, int32* value) const {
    return ParseInt32(data.data(), value);
  }

  template <>
  bool Parse(const std::string& data, int64* value) const {
    return ParseInt64(data.data(), value);
  }

  template <>
  bool Parse(const std::string& data, double* value) const {
    return ParseDouble(data.data(), value);
  }

  template <typename T>
  StatusOr<T> TryParse(const std::string& data) const {
    T result;
    if (!Parse<T>(data, &result)) {
      return Status(StatusCode::INVALID_ARGUMENT, "Could not parse value.");
    }
    return result;
  }

  const SemanticExpressionEvaluator* composer_;
};

}  // namespace libtextclassifier3::grammar

#endif  // LIBTEXTCLASSIFIER_UTILS_GRAMMAR_SEMANTICS_EVALUATORS_PARSE_NUMBER_EVAL_H_
