/*
 *  Copyright 2020 The WebRTC Project Authors. All rights reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#ifndef P2P_BASE_STUN_DICTIONARY_H_
#define P2P_BASE_STUN_DICTIONARY_H_

#include <deque>
#include <map>
#include <memory>
#include <utility>
#include <vector>

#include "api/rtc_error.h"
#include "api/transport/stun.h"

namespace cricket {

// A StunDictionaryView is a dictionary of StunAttributes.
//   - the StunAttributes can be read using the |Get|-methods.
//   - the dictionary is updated by using the |ApplyDelta|-method.
//
// A StunDictionaryWriter is used to create |delta|s for the |ApplyDelta|-method
// - It keeps track of which updates has been applied at StunDictionaryView.
// - It optionally keeps a local StunDictionaryView contains modification made
// `locally`
//
// A pair StunDictionaryView(A)/StunDictionaryWriter(B) are linked so that
// modifications to B is transfered to A using the STUN_ATTR_GOOG_DELTA
// (StunByteStringAttribute) and the modification is ack:ed using
// STUN_ATTR_GOOG_DELTA_ACK (StunUInt64Attribute).
//
// Note:
// 1) It is possible to update one StunDictionaryView from multiple writers,
// but this only works of the different writers write disjoint keys (which
// is not checked/enforced by these classes).
// 2) The opposite, one writer updating multiple StunDictionaryView, is not
// possible.
class StunDictionaryView {
 public:
  // A reserved key used to transport the version number
  static constexpr uint16_t kVersionKey = 0xFFFF;

  // A magic number used when transporting deltas.
  static constexpr uint16_t kDeltaMagic = 0x7788;

  // The version number for the delta format.
  static constexpr uint16_t kDeltaVersion = 0x1;

  // Gets the desired attribute value, or NULL if no such attribute type exists.
  // The pointer returned is guaranteed to be valid until ApplyDelta is called.
  const StunAddressAttribute* GetAddress(int key) const;
  const StunUInt32Attribute* GetUInt32(int key) const;
  const StunUInt64Attribute* GetUInt64(int key) const;
  const StunByteStringAttribute* GetByteString(int key) const;
  const StunUInt16ListAttribute* GetUInt16List(int key) const;

  bool empty() const { return attrs_.empty(); }
  size_t size() const { return attrs_.size(); }
  int bytes_stored() const { return bytes_stored_; }
  void set_max_bytes_stored(int max_bytes_stored) {
    max_bytes_stored_ = max_bytes_stored;
  }

  // Apply a delta and return
  // a pair with
  // - StunUInt64Attribute to ack the |delta|.
  // - vector of keys that was modified.
  webrtc::RTCErrorOr<
      std::pair<std::unique_ptr<StunUInt64Attribute>, std::vector<uint16_t>>>
  ApplyDelta(const StunByteStringAttribute& delta);

 private:
  friend class StunDictionaryWriter;

  const StunAttribute* GetOrNull(
      int key,
      std::optional<StunAttributeValueType> = std::nullopt) const;
  size_t GetLength(int key) const;
  static webrtc::RTCErrorOr<
      std::pair<uint64_t, std::deque<std::unique_ptr<StunAttribute>>>>
  ParseDelta(const StunByteStringAttribute& delta);

  std::map<uint16_t, std::unique_ptr<StunAttribute>> attrs_;
  std::map<uint16_t, uint64_t> version_per_key_;

  int max_bytes_stored_ = 16384;
  int bytes_stored_ = 0;
};

class StunDictionaryWriter {
 public:
  StunDictionaryWriter() {
    dictionary_ = std::make_unique<StunDictionaryView>();
  }
  explicit StunDictionaryWriter(
      std::unique_ptr<StunDictionaryView> dictionary) {
    dictionary_ = std::move(dictionary);
  }

  // A pending modification.
  template <typename T>
  class Modification {
   public:
    ~Modification() { commit(); }

    T* operator->() { return attr_.get(); }

    void abort() { attr_ = nullptr; }
    void commit() {
      if (attr_) {
        writer_->Set(std::move(attr_));
      }
    }

   private:
    friend class StunDictionaryWriter;
    Modification(StunDictionaryWriter* writer, std::unique_ptr<T> attr)
        : writer_(writer), attr_(std::move(attr)) {}
    StunDictionaryWriter* writer_;
    std::unique_ptr<T> attr_;

    Modification(const Modification<T>&) =
        delete;  // not copyable (but movable).
    Modification& operator=(Modification<T>&) =
        delete;  // not copyable (but movable).
  };

  // Record a modification.
  Modification<StunAddressAttribute> SetAddress(int key) {
    return Modification<StunAddressAttribute>(
        this, StunAttribute::CreateAddress(key));
  }
  Modification<StunUInt32Attribute> SetUInt32(int key) {
    return Modification<StunUInt32Attribute>(this,
                                             StunAttribute::CreateUInt32(key));
  }
  Modification<StunUInt64Attribute> SetUInt64(int key) {
    return Modification<StunUInt64Attribute>(this,
                                             StunAttribute::CreateUInt64(key));
  }
  Modification<StunByteStringAttribute> SetByteString(int key) {
    return Modification<StunByteStringAttribute>(
        this, StunAttribute::CreateByteString(key));
  }
  Modification<StunUInt16ListAttribute> SetUInt16List(int key) {
    return Modification<StunUInt16ListAttribute>(
        this, StunAttribute::CreateUInt16ListAttribute(key));
  }

  // Delete a key.
  void Delete(int key);

  // Check if a key has a pending change (i.e a change
  // that has not been acked).
  bool Pending(int key) const;

  // Return number of of pending modifications.
  int Pending() const;

  // Create an StunByteStringAttribute containing the pending (e.g not ack:ed)
  // modifications.
  std::unique_ptr<StunByteStringAttribute> CreateDelta();

  // Apply an delta ack.
  void ApplyDeltaAck(const StunUInt64Attribute&);

  // Return pointer to (optional) StunDictionaryView.
  const StunDictionaryView* dictionary() { return dictionary_.get(); }
  const StunDictionaryView* operator->() { return dictionary_.get(); }

  // Disable writer,
  // i.e CreateDelta always return null, and no modifications are made.
  // This is called if remote peer does not support GOOG_DELTA.
  void Disable();
  bool disabled() const { return disabled_; }

 private:
  void Set(std::unique_ptr<StunAttribute> attr);

  bool disabled_ = false;

  // version of modification.
  int64_t version_ = 1;

  // (optional) StunDictionaryView.
  std::unique_ptr<StunDictionaryView> dictionary_;

  // sorted list of changes that has not been yet been ack:ed.
  std::vector<std::pair<uint64_t, const StunAttribute*>> pending_;

  // tombstones, i.e values that has been deleted but not yet acked.
  std::map<uint16_t, std::unique_ptr<StunAttribute>> tombstones_;
};

}  // namespace cricket

#endif  // P2P_BASE_STUN_DICTIONARY_H_
