// Copyright 2021 The Tint Authors.
//
// 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 "fuzzers/tint_spirv_tools_fuzzer/mutator_cache.h"

namespace tint {
namespace fuzzers {
namespace spvtools_fuzzer {

MutatorCache::MutatorCache(size_t max_size)
    : map_(), entries_(), max_size_(max_size) {
  assert(max_size && "`max_size` may not be 0");
}

MutatorCache::Value::pointer MutatorCache::Get(const Key& key) {
  auto it = map_.find(key);
  if (it == map_.end()) {
    return nullptr;
  }
  UpdateUsage(it);
  return entries_.front().second.get();
}

void MutatorCache::Put(const Key& key, Value value) {
  assert(value && "Mutator cache can't have nullptr unique_ptr");
  auto it = map_.find(key);
  if (it != map_.end()) {
    it->second->second = std::move(value);
    UpdateUsage(it);
  } else {
    if (map_.size() == max_size_) {
      Remove(*entries_.back().first);
    }

    entries_.emplace_front(nullptr, std::move(value));
    auto pair = map_.emplace(key, entries_.begin());
    assert(pair.second && "The key must be unique");
    entries_.front().first = &pair.first->first;
  }
}

MutatorCache::Value MutatorCache::Remove(const Key& key) {
  auto it = map_.find(key);
  if (it == map_.end()) {
    return nullptr;
  }
  auto result = std::move(it->second->second);
  entries_.erase(it->second);
  map_.erase(it);
  return result;
}

size_t MutatorCache::KeyHash::operator()(
    const std::vector<uint32_t>& vec) const {
  return std::hash<std::u32string>()({vec.begin(), vec.end()});
}

void MutatorCache::UpdateUsage(Map::iterator it) {
  auto entry = std::move(*it->second);
  entries_.erase(it->second);
  entries_.push_front(std::move(entry));
  it->second = entries_.begin();
}

}  // namespace spvtools_fuzzer
}  // namespace fuzzers
}  // namespace tint
