/*
 * 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 effectivly
    // 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
