/*
 *  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,
      absl::optional<StunAttributeValueType> = absl::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_
