/*
 * Copyright 2017 The Cobalt Authors. All Rights Reserved.
 *
 * 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 "cobalt/browser/memory_settings/scaling_function.h"

#include <algorithm>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/logging.h"
#include "cobalt/math/clamp.h"
#include "cobalt/math/linear_interpolator.h"

namespace cobalt {
namespace browser {
namespace memory_settings {
namespace {

class JavaScriptGCMemoryScaler {
 public:
  JavaScriptGCMemoryScaler(int64_t min_memory, int64_t max_memory) {
    DCHECK_LE(min_memory, max_memory);
    min_memory = std::min(min_memory, max_memory);
    const double min_factor =
        static_cast<double>(min_memory) / static_cast<double>(max_memory);
    // From 95% -> 0%, the memory will stay the same. This effectively
    // clamps the minimum value.
    interp_table_.Add(0.0, min_factor);

    // At 95% memory, the memory falls to the min_factor. The rationale here
    // is that most of the memory for JavaScript can be eliminated without
    // a large performance penalty, so it's quickly reduced.
    interp_table_.Add(.95, min_factor);

    // At 100% we have 100% of memory.
    interp_table_.Add(1.0, 1.0);
  }
  double Factor(double requested_memory_scale) const {
    return interp_table_.Map(requested_memory_scale);
  }

 private:
  math::LinearInterpolator<double, double> interp_table_;
};

double LinearFunctionWithClampValue(double min_clamp_value,
                                    double max_clamp_value,
                                    double requested_memory_scale) {
  return math::Clamp(requested_memory_scale, min_clamp_value, max_clamp_value);
}

double SkiaAtlasGlyphTextureConstrainer(double requested_memory_scale) {
  if (requested_memory_scale > 0.5f) {
    return 1.0f;
  } else {
    return 0.5f;
  }
}

}  // namespace.

ScalingFunction MakeLinearMemoryScaler(double min_clamp_value,
                                       double max_clamp_value) {
  ScalingFunction function = base::Bind(&LinearFunctionWithClampValue,
                                        min_clamp_value, max_clamp_value);
  return function;
}

ScalingFunction MakeJavaScriptGCScaler(int64_t min_consumption,
                                       int64_t max_consumption) {
  JavaScriptGCMemoryScaler* constrainer =
      new JavaScriptGCMemoryScaler(min_consumption, max_consumption);
  // Note that Bind() will implicitly ref-count the constrainer pointer.
  return base::Bind(&JavaScriptGCMemoryScaler::Factor,
                    base::Owned(constrainer));
}

ScalingFunction MakeSkiaGlyphAtlasMemoryScaler() {
  ScalingFunction function = base::Bind(&SkiaAtlasGlyphTextureConstrainer);
  return function;
}

}  // namespace memory_settings
}  // namespace browser
}  // namespace cobalt
