// Copyright 2022 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
//
//      http://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.

#include "ink_stroke_modeler/params.h"

#include <cmath>

#include "absl/status/status.h"
#include "absl/strings/string_view.h"
#include "absl/strings/substitute.h"
#include "absl/types/variant.h"
#include "ink_stroke_modeler/internal/validation.h"

// This convenience macro evaluates the given expression, and if it does not
// return an OK status, returns and propagates the status.
#define RETURN_IF_ERROR(expr)                              \
  do {                                                     \
    if (auto status = (expr); !status.ok()) return status; \
  } while (false)

namespace ink {
namespace stroke_model {

absl::Status ValidatePositionModelerParams(
    const PositionModelerParams& params) {
  RETURN_IF_ERROR(ValidateGreaterThanZero(params.spring_mass_constant,
                                          "PredictionParams::spring_mass"));
  return ValidateGreaterThanZero(params.drag_constant,
                                 "PredictionParams::drag_ratio");
}

absl::Status ValidateSamplingParams(const SamplingParams& params) {
  RETURN_IF_ERROR(ValidateGreaterThanZero(params.min_output_rate,
                                          "PredictionParams::min_output_rate"));
  RETURN_IF_ERROR(ValidateGreaterThanZero(
      params.end_of_stroke_stopping_distance,
      "PredictionParams::end_of_stroke_stopping_distance"));
  return ValidateGreaterThanZero(
      params.end_of_stroke_max_iterations,
      "PredictionParams::end_of_stroke_stopping_distance");
}

absl::Status ValidateStylusStateModelerParams(
    const StylusStateModelerParams& params) {
  return ValidateGreaterThanZero(params.max_input_samples,
                                 "StylusStateModelerParams::max_input_samples");
}

absl::Status ValidateWobbleSmootherParams(const WobbleSmootherParams& params) {
  RETURN_IF_ERROR(ValidateGreaterThanOrEqualToZero(
      params.timeout.Value(), "WobbleSmootherParams::timeout"));
  RETURN_IF_ERROR(ValidateGreaterThanOrEqualToZero(
      params.speed_floor, "WobbleSmootherParams::speed_floor"));
  RETURN_IF_ERROR(ValidateIsFiniteNumber(
      params.speed_ceiling, "WobbleSmootherParams::speed_ceiling"));
  if (params.speed_ceiling < params.speed_floor) {
    return absl::InvalidArgumentError(absl::Substitute(
        "WobbleSmootherParams::speed_ceiling must be greater than or "
        "equal to WobbleSmootherParams::speed_floor ($0). Actual "
        "value: $1",
        params.speed_floor, params.speed_ceiling));
  }
  return absl::OkStatus();
}

absl::Status ValidatePredictionParams(const PredictionParams& params) {
  if (absl::holds_alternative<StrokeEndPredictorParams>(params)) {
    // Nothing to validate.
    return absl::OkStatus();
  }

  const KalmanPredictorParams& kalman_params =
      absl::get<KalmanPredictorParams>(params);
  RETURN_IF_ERROR(ValidateGreaterThanZero(
      kalman_params.process_noise, "KalmanPredictorParams::process_noise"));
  RETURN_IF_ERROR(
      ValidateGreaterThanZero(kalman_params.measurement_noise,
                              "KalmanPredictorParams::measurement_noise"));
  RETURN_IF_ERROR(
      ValidateGreaterThanZero(kalman_params.min_stable_iteration,
                              "KalmanPredictorParams::min_stable_iteration"));
  RETURN_IF_ERROR(
      ValidateGreaterThanZero(kalman_params.max_time_samples,
                              "KalmanPredictorParams::max_time_samples"));
  RETURN_IF_ERROR(
      ValidateGreaterThanZero(kalman_params.min_catchup_velocity,
                              "KalmanPredictorParams::min_catchup_velocity"));
  RETURN_IF_ERROR(
      ValidateIsFiniteNumber(kalman_params.acceleration_weight,
                             "KalmanPredictorParams::acceleration_weight"));
  RETURN_IF_ERROR(ValidateIsFiniteNumber(kalman_params.jerk_weight,
                                         "KalmanPredictorParams::jerk_weight"));
  RETURN_IF_ERROR(
      ValidateGreaterThanZero(kalman_params.prediction_interval.Value(),
                              "KalmanPredictorParams::jerk_weight"));

  const KalmanPredictorParams::ConfidenceParams& confidence_params =
      kalman_params.confidence_params;
  RETURN_IF_ERROR(ValidateGreaterThanZero(
      confidence_params.desired_number_of_samples,
      "KalmanPredictorParams::ConfidenceParams::desired_number_of_samples"));
  RETURN_IF_ERROR(ValidateGreaterThanZero(
      confidence_params.max_estimation_distance,
      "KalmanPredictorParams::ConfidenceParams::max_estimation_distance"));
  RETURN_IF_ERROR(ValidateGreaterThanOrEqualToZero(
      confidence_params.min_travel_speed,
      "KalmanPredictorParams::ConfidenceParams::min_travel_speed"));
  RETURN_IF_ERROR(ValidateIsFiniteNumber(
      confidence_params.max_travel_speed,
      "KalmanPredictorParams::ConfidenceParams::max_travel_speed"));
  if (confidence_params.max_travel_speed < confidence_params.min_travel_speed) {
    return absl::InvalidArgumentError(
        absl::Substitute("KalmanPredictorParams::ConfidenceParams::max_"
                         "travel_speed must be greater than or equal to "
                         "KalmanPredictorParams::ConfidenceParams::min_"
                         "travel_speed ($0). Actual value: $1",
                         confidence_params.min_travel_speed,
                         confidence_params.max_travel_speed));
  }
  RETURN_IF_ERROR(ValidateGreaterThanZero(
      confidence_params.max_linear_deviation,
      "KalmanPredictorParams::ConfidenceParams::max_linear_deviation"));
  if (confidence_params.baseline_linearity_confidence < 0 ||
      confidence_params.baseline_linearity_confidence > 1) {
    return absl::InvalidArgumentError(absl::Substitute(
        "KalmanPredictorParams::ConfidenceParams::baseline_linearity_"
        "confidence must lie in the interval [0, 1]. Actual value: $0",
        confidence_params.baseline_linearity_confidence));
  }
  return absl::OkStatus();
}

absl::Status ValidateStrokeModelParams(const StrokeModelParams& params) {
  RETURN_IF_ERROR(ValidateWobbleSmootherParams(params.wobble_smoother_params));
  RETURN_IF_ERROR(
      ValidatePositionModelerParams(params.position_modeler_params));
  RETURN_IF_ERROR(ValidateSamplingParams(params.sampling_params));
  RETURN_IF_ERROR(
      ValidateStylusStateModelerParams(params.stylus_state_modeler_params));
  return ValidatePredictionParams(params.prediction_params);
}

}  // namespace stroke_model
}  // namespace ink

#undef RETURN_IF_ERROR
