// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef FLUTTER_FLOW_RASTER_CACHE_KEY_H_
#define FLUTTER_FLOW_RASTER_CACHE_KEY_H_

#include <optional>
#include <unordered_map>
#include <utility>
#include <vector>

#include "flutter/fml/hash_combine.h"
#include "flutter/fml/logging.h"
#include "third_party/skia/include/core/SkMatrix.h"

namespace flutter {

class Layer;

enum class RasterCacheKeyType { kLayer, kDisplayList, kLayerChildren };

class RasterCacheKeyID {
 public:
  static constexpr uint64_t kDefaultUniqueID = 0;

  RasterCacheKeyID(uint64_t unique_id, RasterCacheKeyType type)
      : unique_id_(unique_id), type_(type) {}

  RasterCacheKeyID(std::vector<RasterCacheKeyID> child_ids,
                   RasterCacheKeyType type)
      : unique_id_(kDefaultUniqueID),
        type_(type),
        child_ids_(std::move(child_ids)) {}

  uint64_t unique_id() const { return unique_id_; }

  RasterCacheKeyType type() const { return type_; }

  const std::vector<RasterCacheKeyID>& child_ids() const { return child_ids_; }

  static std::optional<std::vector<RasterCacheKeyID>> LayerChildrenIds(
      const Layer* layer);

  std::size_t GetHash() const {
    if (cached_hash_) {
      return cached_hash_.value();
    }
    std::size_t seed = fml::HashCombine();
    fml::HashCombineSeed(seed, unique_id_);
    fml::HashCombineSeed(seed, type_);
    for (auto& child_id : child_ids_) {
      fml::HashCombineSeed(seed, child_id.GetHash());
    }
    cached_hash_ = seed;
    return seed;
  }

  bool operator==(const RasterCacheKeyID& other) const {
    return unique_id_ == other.unique_id_ && type_ == other.type_ &&
           GetHash() == other.GetHash() && child_ids_ == other.child_ids_;
  }

  bool operator!=(const RasterCacheKeyID& other) const {
    return !operator==(other);
  }

 private:
  const uint64_t unique_id_;
  const RasterCacheKeyType type_;
  const std::vector<RasterCacheKeyID> child_ids_;
  mutable std::optional<std::size_t> cached_hash_;
};

enum class RasterCacheKeyKind { kLayerMetrics, kDisplayListMetrics };

class RasterCacheKey {
 public:
  RasterCacheKey(uint64_t unique_id,
                 RasterCacheKeyType type,
                 const SkMatrix& ctm)
      : RasterCacheKey(RasterCacheKeyID(unique_id, type), ctm) {}

  RasterCacheKey(RasterCacheKeyID id, const SkMatrix& ctm)
      : id_(std::move(id)), matrix_(ctm) {
    matrix_[SkMatrix::kMTransX] = 0;
    matrix_[SkMatrix::kMTransY] = 0;
  }

  const RasterCacheKeyID& id() const { return id_; }
  const SkMatrix& matrix() const { return matrix_; }

  RasterCacheKeyKind kind() const {
    switch (id_.type()) {
      case RasterCacheKeyType::kDisplayList:
        return RasterCacheKeyKind::kDisplayListMetrics;
      case RasterCacheKeyType::kLayer:
      case RasterCacheKeyType::kLayerChildren:
        return RasterCacheKeyKind::kLayerMetrics;
    }
  }

  struct Hash {
    std::size_t operator()(RasterCacheKey const& key) const {
      return key.id_.GetHash();
    }
  };

  struct Equal {
    constexpr bool operator()(const RasterCacheKey& lhs,
                              const RasterCacheKey& rhs) const {
      return lhs.id_ == rhs.id_ && lhs.matrix_ == rhs.matrix_;
    }
  };

  template <class Value>
  using Map = std::unordered_map<RasterCacheKey, Value, Hash, Equal>;

 private:
  RasterCacheKeyID id_;

  // ctm where only fractional (0-1) translations are preserved:
  //   matrix_ = ctm;
  //   matrix_[SkMatrix::kMTransX] = SkScalarFraction(ctm.getTranslateX());
  //   matrix_[SkMatrix::kMTransY] = SkScalarFraction(ctm.getTranslateY());
  SkMatrix matrix_;
};

}  // namespace flutter

#endif  // FLUTTER_FLOW_RASTER_CACHE_KEY_H_
