// Copyright 2019 The Chromium 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 BASE_WIN_MAP_H_
#define BASE_WIN_MAP_H_

#include <windows.foundation.collections.h>
#include <wrl/implements.h>

#include <map>

#include "base/stl_util.h"
#include "base/win/vector.h"
#include "base/win/winrt_foundation_helpers.h"

namespace base {
namespace win {

template <typename K, typename V>
class Map;

namespace internal {

// Template tricks needed to dispatch to the correct implementation.
// See base/win/winrt_foundation_helpers.h for explanation.

template <typename K, typename V>
using ComplexK =
    typename ABI::Windows::Foundation::Collections::IMap<K, V>::K_complex;

template <typename K, typename V>
using ComplexV =
    typename ABI::Windows::Foundation::Collections::IMap<K, V>::V_complex;

template <typename K, typename V>
using LogicalK = LogicalType<ComplexK<K, V>>;

template <typename K, typename V>
using LogicalV = LogicalType<ComplexV<K, V>>;

template <typename K, typename V>
using AbiK = AbiType<ComplexK<K, V>>;

template <typename K, typename V>
using AbiV = AbiType<ComplexV<K, V>>;

template <typename K, typename V>
using StorageK = StorageType<ComplexK<K, V>>;

template <typename K, typename V>
using StorageV = StorageType<ComplexV<K, V>>;

template <typename K, typename V>
class KeyValuePair : public Microsoft::WRL::RuntimeClass<
                         Microsoft::WRL::RuntimeClassFlags<
                             Microsoft::WRL::WinRtClassicComMix |
                             Microsoft::WRL::InhibitRoOriginateError>,
                         ABI::Windows::Foundation::Collections::
                             IKeyValuePair<LogicalK<K, V>, LogicalV<K, V>>> {
 public:
  using AbiK = AbiK<K, V>;
  using AbiV = AbiV<K, V>;
  using StorageK = StorageK<K, V>;
  using StorageV = StorageV<K, V>;

  KeyValuePair(StorageK key, StorageV value)
      : key_(std::move(key)), value_(std::move(value)) {}

  // ABI::Windows::Foundation::Collections::IKeyValuePair:
  IFACEMETHODIMP get_Key(AbiK* key) { return CopyTo(key_, key); }

  IFACEMETHODIMP get_Value(AbiV* value) { return CopyTo(value_, value); }

 private:
  StorageK key_;
  StorageV value_;
};

template <typename K>
class MapChangedEventArgs
    : public Microsoft::WRL::RuntimeClass<
          Microsoft::WRL::RuntimeClassFlags<
              Microsoft::WRL::WinRtClassicComMix |
              Microsoft::WRL::InhibitRoOriginateError>,
          ABI::Windows::Foundation::Collections::IMapChangedEventArgs<K>> {
 public:
  MapChangedEventArgs(
      ABI::Windows::Foundation::Collections::CollectionChange change,
      K key)
      : change_(change), key_(std::move(key)) {}

  ~MapChangedEventArgs() override = default;

  // ABI::Windows::Foundation::Collections::IMapChangedEventArgs:
  IFACEMETHODIMP get_CollectionChange(
      ABI::Windows::Foundation::Collections::CollectionChange* value) override {
    *value = change_;
    return S_OK;
  }

  IFACEMETHODIMP get_Key(K* value) override {
    *value = key_;
    return S_OK;
  }

 private:
  const ABI::Windows::Foundation::Collections::CollectionChange change_;
  K key_;
};

}  // namespace internal

// This file provides an implementation of Windows::Foundation::IMap. It
// functions as a thin wrapper around an std::map, and dispatches
// method calls to either the corresponding std::map API or
// appropriate std algorithms. Furthermore, it notifies its observers whenever
// its observable state changes, and is iterable. Please notice also that if the
// map is modified while iterating over it, iterator methods will return
// E_CHANGED_STATE. A base::win::Map can be constructed for any types <K,V>, and
// is implicitly constructible from a std::map. In the case where K or V is a
// pointer derived from IUnknown, the std::map needs to be of type
// Microsoft::WRL::ComPtr<K> or Microsoft::WRL::ComPtr<V>. This enforces proper
// reference counting and improves safety.
template <typename K, typename V>
class Map
    : public Microsoft::WRL::RuntimeClass<
          Microsoft::WRL::RuntimeClassFlags<
              Microsoft::WRL::WinRt | Microsoft::WRL::InhibitRoOriginateError>,
          ABI::Windows::Foundation::Collections::IMap<internal::LogicalK<K, V>,
                                                      internal::LogicalV<K, V>>,
          ABI::Windows::Foundation::Collections::IObservableMap<
              internal::LogicalK<K, V>,
              internal::LogicalV<K, V>>,
          ABI::Windows::Foundation::Collections::IIterable<
              ABI::Windows::Foundation::Collections::IKeyValuePair<
                  internal::LogicalK<K, V>,
                  internal::LogicalV<K, V>>*>> {
 public:
  using LogicalK = internal::LogicalK<K, V>;
  using LogicalV = internal::LogicalV<K, V>;
  using AbiK = internal::AbiK<K, V>;
  using AbiV = internal::AbiV<K, V>;
  using StorageK = internal::StorageK<K, V>;
  using StorageV = internal::StorageV<K, V>;

 private:
  class MapView;

  // Iterates over base::win::Map.
  // Its methods return E_CHANGED_STATE is the map is modified.
  // TODO(https://crbug.com/987533): Refactor MapIterator to leverage
  // std::map::iterator.
  class MapIterator
      : public Microsoft::WRL::RuntimeClass<
            Microsoft::WRL::RuntimeClassFlags<
                Microsoft::WRL::WinRtClassicComMix |
                Microsoft::WRL::InhibitRoOriginateError>,
            ABI::Windows::Foundation::Collections::IIterator<
                ABI::Windows::Foundation::Collections::IKeyValuePair<
                    internal::LogicalK<K, V>,
                    internal::LogicalV<K, V>>*>> {
   public:
    explicit MapIterator(Microsoft::WRL::ComPtr<MapView> view)
        : view_(std::move(view)) {
      DCHECK(view_->ValidState());
      ConvertMapToVectorIterator();
    }

    // ABI::Windows::Foundation::Collections::IIterator:
    IFACEMETHODIMP get_Current(
        ABI::Windows::Foundation::Collections::IKeyValuePair<LogicalK,
                                                             LogicalV>**
            current) override {
      return view_->ValidState() ? iterator_->get_Current(current)
                                 : E_CHANGED_STATE;
    }

    IFACEMETHODIMP get_HasCurrent(boolean* has_current) override {
      return view_->ValidState() ? iterator_->get_HasCurrent(has_current)
                                 : E_CHANGED_STATE;
    }

    IFACEMETHODIMP MoveNext(boolean* has_current) override {
      return view_->ValidState() ? iterator_->MoveNext(has_current)
                                 : E_CHANGED_STATE;
    }

    IFACEMETHODIMP GetMany(
        unsigned capacity,
        ABI::Windows::Foundation::Collections::IKeyValuePair<LogicalK,
                                                             LogicalV>** value,
        unsigned* actual) override {
      return view_->ValidState() ? iterator_->GetMany(capacity, value, actual)
                                 : E_CHANGED_STATE;
    }

   private:
    // Helper for iteration:
    void ConvertMapToVectorIterator() {
      // Create a vector that will hold Map's key-value pairs.
      auto vector = Microsoft::WRL::Make<
          Vector<ABI::Windows::Foundation::Collections::IKeyValuePair<
              LogicalK, LogicalV>*>>();

      // Fill the vector with container data.
      for (const auto& pair : view_->get_map()) {
        auto key_value_pair =
            Microsoft::WRL::Make<internal::KeyValuePair<AbiK, AbiV>>(
                pair.first, pair.second);
        vector->Append(key_value_pair.Get());
      }

      // Return an iterator to that vector.
      // Iterator is immutable (wraps an IVectorView) and Vector's lifecycle is
      // ensured cause the view holds a reference to the vector, and iterator
      // holds a reference to the view.
      HRESULT hr = vector->First(&iterator_);
      DCHECK(SUCCEEDED(hr));
    }

    Microsoft::WRL::ComPtr<MapView> view_;
    Microsoft::WRL::ComPtr<ABI::Windows::Foundation::Collections::IIterator<
        ABI::Windows::Foundation::Collections::IKeyValuePair<LogicalK,
                                                             LogicalV>*>>
        iterator_;
  };

  class MapView
      : public Microsoft::WRL::RuntimeClass<
            Microsoft::WRL::RuntimeClassFlags<
                Microsoft::WRL::WinRtClassicComMix |
                Microsoft::WRL::InhibitRoOriginateError>,
            ABI::Windows::Foundation::Collections::
                IMapView<internal::LogicalK<K, V>, internal::LogicalV<K, V>>,
            ABI::Windows::Foundation::Collections::IIterable<
                ABI::Windows::Foundation::Collections::IKeyValuePair<
                    internal::LogicalK<K, V>,
                    internal::LogicalV<K, V>>*>,
            ABI::Windows::Foundation::Collections::MapChangedEventHandler<
                internal::LogicalK<K, V>,
                internal::LogicalV<K, V>>> {
   public:
    explicit MapView(Microsoft::WRL::ComPtr<Map<LogicalK, LogicalV>> map)
        : map_(std::move(map)) {
      map_->add_MapChanged(this, &map_changed_token_);
    }

    ~MapView() {
      if (map_)
        map_->remove_MapChanged(map_changed_token_);
    }

    // ABI::Windows::Foundation::Collections::IMapView:
    IFACEMETHODIMP Lookup(AbiK key, AbiV* value) override {
      return map_ ? map_->Lookup(key, value) : E_CHANGED_STATE;
    }

    IFACEMETHODIMP get_Size(unsigned int* size) override {
      return map_ ? map_->get_Size(size) : E_CHANGED_STATE;
    }

    IFACEMETHODIMP HasKey(AbiK key, boolean* found) override {
      return map_ ? map_->HasKey(key, found) : E_CHANGED_STATE;
    }

    IFACEMETHODIMP Split(
        ABI::Windows::Foundation::Collections::IMapView<LogicalK, LogicalV>**
            first_partition,
        ABI::Windows::Foundation::Collections::IMapView<LogicalK, LogicalV>**
            second_partition) override {
      NOTIMPLEMENTED();
      return E_NOTIMPL;
    }

    // ABI::Windows::Foundation::Collections::IIterable:
    IFACEMETHODIMP First(
        ABI::Windows::Foundation::Collections::IIterator<
            ABI::Windows::Foundation::Collections::IKeyValuePair<LogicalK,
                                                                 LogicalV>*>**
            first) override {
      return map_ ? map_->First(first) : E_CHANGED_STATE;
    }

    // ABI::Windows::Foundation::Collections::MapChangedEventHandler:
    IFACEMETHODIMP Invoke(
        ABI::Windows::Foundation::Collections::IObservableMap<LogicalK,
                                                              LogicalV>* sender,
        ABI::Windows::Foundation::Collections::IMapChangedEventArgs<LogicalK>*
            e) override {
      DCHECK_EQ(map_.Get(), sender);
      map_.Reset();
      sender->remove_MapChanged(map_changed_token_);
      return S_OK;
    }

    // Accessor used in MapIterator for iterating over Map's container.
    // Will remain valid during the entire iteration.
    const std::map<StorageK, StorageV, internal::Less>& get_map() {
      DCHECK(map_);
      return map_->map_;
    }

    bool ValidState() const { return map_; }

   private:
    Microsoft::WRL::ComPtr<Map<LogicalK, LogicalV>> map_;
    EventRegistrationToken map_changed_token_;
  };

 public:
  Map() = default;
  explicit Map(const std::map<StorageK, StorageV, internal::Less>& map)
      : map_(map) {}
  explicit Map(std::map<StorageK, StorageV, internal::Less>&& map)
      : map_(std::move(map)) {}

  // ABI::Windows::Foundation::Collections::IMap:
  IFACEMETHODIMP Lookup(AbiK key, AbiV* value) override {
    auto it = map_.find(key);
    if (it == map_.cend())
      return E_BOUNDS;

    return internal::CopyTo(it->second, value);
  }

  IFACEMETHODIMP get_Size(unsigned int* size) override {
    *size = map_.size();
    return S_OK;
  }

  IFACEMETHODIMP HasKey(AbiK key, boolean* found) override {
    *found = Contains(map_, key);
    return S_OK;
  }

  IFACEMETHODIMP GetView(
      ABI::Windows::Foundation::Collections::IMapView<LogicalK, LogicalV>**
          view) override {
    return Microsoft::WRL::Make<MapView>(this).CopyTo(view);
  }

  IFACEMETHODIMP Insert(AbiK key, AbiV value, boolean* replaced) override {
    *replaced = !InsertOrAssign(map_, key, std::move(value)).second;
    NotifyMapChanged(*replaced ? ABI::Windows::Foundation::Collections::
                                     CollectionChange_ItemChanged
                               : ABI::Windows::Foundation::Collections::
                                     CollectionChange_ItemInserted,
                     key);
    return S_OK;
  }

  IFACEMETHODIMP Remove(AbiK key) override {
    if (!map_.erase(key))
      return E_BOUNDS;

    NotifyMapChanged(
        ABI::Windows::Foundation::Collections::CollectionChange_ItemRemoved,
        key);
    return S_OK;
  }

  IFACEMETHODIMP Clear() override {
    map_.clear();
    NotifyMapChanged(
        ABI::Windows::Foundation::Collections::CollectionChange_Reset, 0);
    return S_OK;
  }

  // ABI::Windows::Foundation::Collections::IObservableMap:
  IFACEMETHODIMP add_MapChanged(
      ABI::Windows::Foundation::Collections::MapChangedEventHandler<LogicalK,
                                                                    LogicalV>*
          handler,
      EventRegistrationToken* token) override {
    token->value = handler_id_++;
    handlers_.emplace_hint(handlers_.end(), token->value, handler);
    return S_OK;
  }

  IFACEMETHODIMP remove_MapChanged(EventRegistrationToken token) override {
    return handlers_.erase(token.value) ? S_OK : E_BOUNDS;
  }

  // ABI::Windows::Foundation::Collections::IIterable:
  IFACEMETHODIMP First(
      ABI::Windows::Foundation::Collections::IIterator<
          ABI::Windows::Foundation::Collections::IKeyValuePair<LogicalK,
                                                               LogicalV>*>**
          first) override {
    return Microsoft::WRL::Make<MapIterator>(
               Microsoft::WRL::Make<MapView>(this))
        .CopyTo(first);
  }

 private:
  ~Map() override {
    // Handlers should not outlive the Map. Furthermore, they must ensure
    // they are unregistered before the the handler is destroyed. This implies
    // there should be no handlers left when the Map is destructed.
    DCHECK(handlers_.empty());
  }

  void NotifyMapChanged(
      ABI::Windows::Foundation::Collections::CollectionChange change,
      AbiK key) {
    auto args =
        Microsoft::WRL::Make<internal::MapChangedEventArgs<AbiK>>(change, key);

    // Invoking the handlers could result in mutations to the map, thus we make
    // a copy beforehand.
    auto handlers = handlers_;
    for (auto& handler : handlers)
      handler.second->Invoke(this, args.Get());
  }

  std::map<StorageK, StorageV, internal::Less> map_;
  base::flat_map<int64_t,
                 ABI::Windows::Foundation::Collections::
                     MapChangedEventHandler<LogicalK, LogicalV>*>
      handlers_;
  int64_t handler_id_ = 0;
};

}  // namespace win
}  // namespace base

#endif  // BASE_WIN_MAP_H_
