// Copyright 2022 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 "pw_assert/assert.h"
#include "pw_containers/intrusive_list.h"
#include "pw_status/status.h"
#include "pw_stream/stream.h"
#include "pw_transfer/internal/event.h"

namespace pw::transfer {
namespace internal {

// The internal::Handler class is the base class for the transfer handler
// classes. Transfer handlers connect a transfer resource ID to the functions
// that do the actual reads and/or writes.
//
// Handlers use a stream::Reader or stream::Writer to do the reads and writes.
// They also provide optional Prepare and Finalize functions.
class Handler : public IntrusiveList<Handler>::Item {
 public:
  virtual ~Handler() = default;

  constexpr uint32_t id() const { return resource_id_; }

  // Called at the beginning of a read transfer. The stream::Reader must be
  // ready to read after a successful PrepareRead() call. Returning a non-OK
  // status aborts the read.
  //
  // Status::Unimplemented() indicates that reads are not supported.
  virtual Status PrepareRead() = 0;

  // FinalizeRead() is called at the end of a read transfer. The status argument
  // indicates whether the data transfer was successful or not.
  virtual void FinalizeRead(Status) {}

  // Called at the beginning of a write transfer. The stream::Writer must be
  // ready to read after a successful PrepareRead() call. Returning a non-OK
  // status aborts the write.
  //
  // Status::Unimplemented() indicates that writes are not supported.
  virtual Status PrepareWrite() = 0;

  // FinalizeWrite() is called at the end of a write transfer. The status
  // argument indicates whether the data transfer was successful or not.
  //
  // Returning an error signals that the transfer failed, even if it had
  // succeeded up to this point.
  virtual Status FinalizeWrite(Status) { return OkStatus(); }

 protected:
  constexpr Handler(uint32_t resource_id, stream::Reader* reader)
      : resource_id_(resource_id), reader_(reader) {}

  constexpr Handler(uint32_t resource_id, stream::Writer* writer)
      : resource_id_(resource_id), writer_(writer) {}

  void set_reader(stream::Reader& reader) { reader_ = &reader; }
  void set_writer(stream::Writer& writer) { writer_ = &writer; }

 private:
  friend class Context;

  // Prepares for either a read or write transfer.
  Status Prepare(internal::TransferType type) {
    return type == internal::TransferType::kTransmit ? PrepareRead()
                                                     : PrepareWrite();
  }

  // Only valid after a PrepareRead() or PrepareWrite() call that returns OK.
  stream::Stream& stream() const {
    PW_DASSERT(reader_ != nullptr);
    return *reader_;
  }

  uint32_t resource_id_;

  // Use a union to support constexpr construction.
  union {
    stream::Reader* reader_;
    stream::Writer* writer_;
  };
};

}  // namespace internal

class ReadOnlyHandler : public internal::Handler {
 public:
  constexpr ReadOnlyHandler(uint32_t resource_id)
      : internal::Handler(resource_id, static_cast<stream::Reader*>(nullptr)) {}

  constexpr ReadOnlyHandler(uint32_t resource_id, stream::Reader& reader)
      : internal::Handler(resource_id, &reader) {}

  virtual ~ReadOnlyHandler() = default;

  Status PrepareRead() override { return OkStatus(); }

  // Writes are not supported.
  Status PrepareWrite() final { return Status::PermissionDenied(); }

  using internal::Handler::set_reader;

 private:
  using internal::Handler::set_writer;
};

class WriteOnlyHandler : public internal::Handler {
 public:
  constexpr WriteOnlyHandler(uint32_t resource_id)
      : internal::Handler(resource_id, static_cast<stream::Writer*>(nullptr)) {}

  constexpr WriteOnlyHandler(uint32_t resource_id, stream::Writer& writer)
      : internal::Handler(resource_id, &writer) {}

  virtual ~WriteOnlyHandler() = default;

  // Reads are not supported.
  Status PrepareRead() final { return Status::PermissionDenied(); }

  Status PrepareWrite() override { return OkStatus(); }

  using internal::Handler::set_writer;

 private:
  using internal::Handler::set_reader;
};

class ReadWriteHandler : public internal::Handler {
 public:
  constexpr ReadWriteHandler(uint32_t resource_id)
      : internal::Handler(resource_id, static_cast<stream::Reader*>(nullptr)) {}
  constexpr ReadWriteHandler(uint32_t resource_id,
                             stream::ReaderWriter& reader_writer)
      : internal::Handler(resource_id,
                          &static_cast<stream::Reader&>(reader_writer)) {}

  virtual ~ReadWriteHandler() = default;

  // Both reads and writes are supported.
  Status PrepareRead() override { return OkStatus(); }
  Status PrepareWrite() override { return OkStatus(); }

  void set_reader_writer(stream::ReaderWriter& reader_writer) {
    set_reader(reader_writer);
  }
};

}  // namespace pw::transfer
