// Copyright 2020 The Pigweed 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
//
//     https://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.
#pragma once

#include <cstdint>
#include <limits>
#include <span>
#include <type_traits>

#include "pw_assert/assert.h"
#include "pw_bytes/span.h"
#include "pw_result/result.h"
#include "pw_rpc/internal/lock.h"
#include "pw_status/status.h"

namespace pw::rpc {

// Extracts the channel ID from a pw_rpc packet. Returns DATA_LOSS if the
// packet is corrupt and the channel ID could not be found.
Result<uint32_t> ExtractChannelId(ConstByteSpan packet);

class ChannelOutput {
 public:
  // Returned from MaximumTransmissionUnit() to indicate that this ChannelOutput
  // imposes no limits on the MTU.
  static constexpr size_t kUnlimited = std::numeric_limits<size_t>::max();

  // Creates a channel output with the provided name. The name is used for
  // logging only.
  constexpr ChannelOutput(const char* name) : name_(name) {}

  virtual ~ChannelOutput() = default;

  constexpr const char* name() const { return name_; }

  // Returns the maximum transmission unit that this ChannelOutput supports. If
  // the ChannelOutput imposes no limit on the MTU, this function returns
  // ChannelOutput::kUnlimited.
  virtual size_t MaximumTransmissionUnit() { return kUnlimited; }

  // Sends an encoded RPC packet. Returns OK if further packets may be sent,
  // even if the current packet could not be sent. Returns any other status if
  // the Channel is no longer able to send packets.
  //
  // The RPC system’s internal lock is held while this function is called. Avoid
  // long-running operations, since these will delay any other users of the RPC
  // system.
  //
  // !!! DANGER !!!
  //
  // No pw_rpc APIs may be accessed in this function! Implementations MUST NOT
  // access any RPC endpoints (pw::rpc::Client, pw::rpc::Server) or call objects
  // (pw::rpc::ServerReaderWriter, pw::rpc::ClientReaderWriter, etc.) inside the
  // Send() function or any descendent calls. Doing so will result in deadlock!
  // RPC APIs may be used by other threads, just not within Send().
  //
  // The buffer provided in packet must NOT be accessed outside of this
  // function. It must be sent immediately or copied elsewhere before the
  // function returns.
  virtual Status Send(std::span<const std::byte> buffer)
      PW_EXCLUSIVE_LOCKS_REQUIRED(internal::rpc_lock()) = 0;

 private:
  const char* name_;
};

class Channel {
 public:
  static constexpr uint32_t kUnassignedChannelId = 0;

  // Creates a channel with a static ID. The channel's output can also be
  // static, or it can set to null to allow dynamically opening connections
  // through the channel.
  template <uint32_t kId>
  constexpr static Channel Create(ChannelOutput* output) {
    static_assert(kId != kUnassignedChannelId, "Channel ID cannot be 0");
    return Channel(kId, output);
  }

  // Creates a channel with a static ID from an enum value.
  template <auto kId,
            typename T = decltype(kId),
            typename = std::enable_if_t<std::is_enum_v<T>>,
            typename U = std::underlying_type_t<T>>
  constexpr static Channel Create(ChannelOutput* output) {
    constexpr U kIntId = static_cast<U>(kId);
    static_assert(kIntId >= 0, "Channel ID cannot be negative");
    static_assert(kIntId <= std::numeric_limits<uint32_t>::max(),
                  "Channel ID must fit in a uint32");
    return Create<static_cast<uint32_t>(kIntId)>(output);
  }

  // Creates a dynamically assignable channel without a set ID or output.
  constexpr Channel() : id_(kUnassignedChannelId), output_(nullptr) {}

  // TODO(pwbug/620): Remove the Configure and set_channel_output functions.
  //     Users should call CloseChannel() / OpenChannel() to change a channel.
  //     This ensures calls are properly update and works consistently between
  //     static and dynamic channel allocation.

  // Manually configures a dynamically-assignable channel with a specified ID
  // and output. This is useful when a channel's parameters are not known until
  // runtime. This can only be called once per channel.
  template <typename UnusedType = void>
  constexpr void Configure(uint32_t id, ChannelOutput& output) {
    static_assert(
        !cfg::kDynamicAllocationEnabled<UnusedType>,
        "Configure() may not be used if PW_RPC_DYNAMIC_ALLOCATION is "
        "enabled. Call CloseChannel/OpenChannel on the endpoint instead.");
    PW_ASSERT(id_ == kUnassignedChannelId);
    PW_ASSERT(id != kUnassignedChannelId);
    id_ = id;
    output_ = &output;
  }

  // Configure using an enum value channel ID.
  template <typename T,
            typename = std::enable_if_t<std::is_enum_v<T>>,
            typename U = std::underlying_type_t<T>>
  constexpr void Configure(T id, ChannelOutput& output) {
    static_assert(
        !cfg::kDynamicAllocationEnabled<T>,
        "Configure() may not be used if PW_RPC_DYNAMIC_ALLOCATION is enabled. "
        "Call CloseChannel/OpenChannel on the endpoint instead.");
    static_assert(sizeof(U) <= sizeof(uint32_t));
    const U kIntId = static_cast<U>(id);
    PW_ASSERT(kIntId > 0);
    return Configure<T>(static_cast<uint32_t>(kIntId), output);
  }

  // Reconfigures a channel with a new output. Depending on the output's
  // implementatation, there might be unintended behavior if the output is in
  // use.
  template <typename UnusedType = void>
  constexpr void set_channel_output(ChannelOutput& output) {
    static_assert(
        !cfg::kDynamicAllocationEnabled<UnusedType>,
        "set_channel_output() may not be used if PW_RPC_DYNAMIC_ALLOCATION is "
        "enabled. Call CloseChannel/OpenChannel on the endpoint instead.");
    PW_ASSERT(id_ != kUnassignedChannelId);
    output_ = &output;
  }

  constexpr uint32_t id() const { return id_; }
  constexpr bool assigned() const { return id_ != kUnassignedChannelId; }

 protected:
  constexpr Channel(uint32_t id, ChannelOutput* output)
      : id_(id), output_(output) {
    PW_ASSERT(id != kUnassignedChannelId);
  }

  ChannelOutput& output() const {
    PW_ASSERT(output_ != nullptr);
    return *output_;
  }

  void set_channel_id(uint32_t channel_id) { id_ = channel_id; }

  constexpr void Close() {
    PW_ASSERT(id_ != kUnassignedChannelId);
    id_ = kUnassignedChannelId;
    output_ = nullptr;
  }

 private:
  uint32_t id_;
  ChannelOutput* output_;
};

}  // namespace pw::rpc
