/*
 * Copyright 2017 Google Inc. 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.
 */

#ifndef COBALT_BROWSER_MEMORY_SETTINGS_TEST_COMMON_H_
#define COBALT_BROWSER_MEMORY_SETTINGS_TEST_COMMON_H_

#include <map>
#include <sstream>
#include <string>
#include <vector>

#include "base/compiler_specific.h"
#include "cobalt/browser/memory_settings/memory_settings.h"
#include "cobalt/browser/memory_settings/texture_dimensions.h"
#include "cobalt/browser/switches.h"
#include "cobalt/math/size.h"
#include "testing/gtest/include/gtest/gtest.h"

// PrintToString() provides the proper functionality to pretty print custom
// types.

namespace testing {

template <>
inline ::std::string PrintToString(const cobalt::math::Size& value) {
  ::std::stringstream ss;
  ss << "math::Size(" << value.width() << ", " << value.height() << ")";
  return ss.str();
}

template <>
inline ::std::string PrintToString(
    const cobalt::browser::memory_settings::TextureDimensions& value) {
  ::std::stringstream ss;
  ss << "TextureDimensions(" << value.width() << "x" << value.height() << "x"
     << value.bytes_per_pixel() << ")";
  return ss.str();
}

}  // namespace testing

namespace cobalt {
namespace browser {
namespace memory_settings {

class TestDimensionSetting : public DimensionSetting {
 public:
  explicit TestDimensionSetting(const std::string& name)
      : DimensionSetting(name) {}
  virtual void ScaleMemory(double absolute_constraining_value) {
    UNREFERENCED_PARAMETER(absolute_constraining_value);
  }
};

class TestSettingGroup {
 public:
  TestSettingGroup() {}

  void LoadDefault() {
    MakeSetting(MemorySetting::kCmdLine, MemorySetting::kGPU,
                switches::kImageCacheSizeInBytes, 1234);

    MakeSetting(MemorySetting::kAutoSet, MemorySetting::kCPU,
                switches::kJavaScriptGcThresholdInBytes, 1112);

    MakeSetting(MemorySetting::kCmdLine, MemorySetting::kGPU,
                switches::kSkiaTextureAtlasDimensions,
                TextureDimensions(1234, 4567, 2));

    MakeSetting(MemorySetting::kCmdLine, MemorySetting::kGPU,
                switches::kSkiaCacheSizeInBytes, 12345678);

    MakeSetting(MemorySetting::kBuildSetting, MemorySetting::kNotApplicable,
                switches::kSoftwareSurfaceCacheSizeInBytes, 8910);
  }

  ~TestSettingGroup() {
    for (MemoryMap::const_iterator it = map_.begin(); it != map_.end(); ++it) {
      delete it->second;
    }
  }

  // The memory setting is owned internally.
  template <typename ValueType>
  void MakeSetting(MemorySetting::SourceType source_type,
                   MemorySetting::MemoryType memory_type,
                   const std::string& name, const ValueType& value) {
    const bool found = (map_.find(name) !=  map_.end());

    ASSERT_FALSE(found);
    map_[name] = CreateMemorySetting(source_type, memory_type, name, value);
  }

  std::vector<const MemorySetting*> AsConstVector() const {
    std::vector<const MemorySetting*> output;
    for (MemoryMap::const_iterator it = map_.begin(); it != map_.end(); ++it) {
      output.push_back(it->second);
    }
    return output;
  }

  std::vector<MemorySetting*> AsMutableVector() {
    std::vector<MemorySetting*> output;
    for (MemoryMap::iterator it = map_.begin(); it != map_.end(); ++it) {
      output.push_back(it->second);
    }
    return output;
  }

 private:
  template <typename ValueType>
  static MemorySetting* CreateMemorySetting(
      MemorySetting::SourceType source_type,
      MemorySetting::MemoryType memory_type, const std::string& name,
      const ValueType& value) {
    IntSetting* memory_setting = new IntSetting(name);
    memory_setting->set_memory_type(memory_type);
    memory_setting->set_value(source_type, value);
    return memory_setting;
  }

  typedef std::map<std::string, MemorySetting*> MemoryMap;
  MemoryMap map_;
};

// Specialization for TextureDimensions.

// static
template <>
inline MemorySetting* TestSettingGroup::CreateMemorySetting(
    MemorySetting::SourceType source_type,
    MemorySetting::MemoryType memory_type, const std::string& name,
    const TextureDimensions& value) {
  TestDimensionSetting* memory_setting = new TestDimensionSetting(name);
  memory_setting->set_memory_type(memory_type);
  memory_setting->set_value(source_type, value);
  return memory_setting;
}

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

#endif  // COBALT_BROWSER_MEMORY_SETTINGS_TEST_COMMON_H_
