// Copyright 2013 The Flutter 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 FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_EVENT_CHANNEL_H_
#define FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_EVENT_CHANNEL_H_

#include <iostream>
#include <memory>
#include <string>

#include "binary_messenger.h"
#include "engine_method_result.h"
#include "event_sink.h"
#include "event_stream_handler.h"

namespace flutter {

// A named channel for communicating with the Flutter application using
// asynchronous event streams. Incoming requests for event stream setup are
// decoded from binary on receipt, and C++ responses and events are encoded into
// binary before being transmitted back to Flutter. The MethodCodec used must be
// compatible with the one used by the Flutter application. This can be achieved
// by creating an EventChannel
// ("https://docs.flutter.io/flutter/services/EventChannel-class.html")
// counterpart of this channel on the Dart side.
// The C++ type of stream configuration arguments, events, and error details are
// templated, but only values supported by the specified MethodCodec can be
// used.
template <typename T>
class EventChannel {
 public:
  // Creates an instance that sends and receives event handler on the channel
  // named |name|, encoded with |codec| and dispatched via |messenger|.
  EventChannel(BinaryMessenger* messenger,
               const std::string& name,
               const MethodCodec<T>* codec)
      : messenger_(messenger), name_(name), codec_(codec) {}
  ~EventChannel() = default;

  // Prevent copying.
  EventChannel(EventChannel const&) = delete;
  EventChannel& operator=(EventChannel const&) = delete;

  // Registers a stream handler on this channel.
  // If no handler has been registered, any incoming stream setup requests will
  // be handled silently by providing an empty stream.
  void SetStreamHandler(std::unique_ptr<StreamHandler<T>> handler) {
    if (!handler) {
      messenger_->SetMessageHandler(name_, nullptr);
      is_listening_ = false;
      return;
    }

    // std::function requires a copyable lambda, so convert to a shared pointer.
    // This is safe since only one copy of the shared_pointer will ever be
    // accessed.
    std::shared_ptr<StreamHandler<T>> shared_handler(handler.release());
    const MethodCodec<T>* codec = codec_;
    const std::string channel_name = name_;
    const BinaryMessenger* messenger = messenger_;
    BinaryMessageHandler binary_handler = [shared_handler, codec, channel_name,
                                           messenger,
                                           this](const uint8_t* message,
                                                 const size_t message_size,
                                                 BinaryReply reply) {
      constexpr char kOnListenMethod[] = "listen";
      constexpr char kOnCancelMethod[] = "cancel";

      std::unique_ptr<MethodCall<T>> method_call =
          codec->DecodeMethodCall(message, message_size);
      if (!method_call) {
        std::cerr << "Unable to construct method call from message on channel: "
                  << channel_name << std::endl;
        reply(nullptr, 0);
        return;
      }

      const std::string& method = method_call->method_name();
      if (method.compare(kOnListenMethod) == 0) {
        if (is_listening_) {
          std::unique_ptr<StreamHandlerError<T>> error =
              shared_handler->OnCancel(nullptr);
          if (error) {
            std::cerr << "Failed to cancel existing stream: "
                      << (error->error_code) << ", " << (error->error_message)
                      << ", " << (error->error_details);
          }
        }
        is_listening_ = true;

        std::unique_ptr<std::vector<uint8_t>> result;
        auto sink = std::make_unique<EventSinkImplementation>(
            messenger, channel_name, codec);
        std::unique_ptr<StreamHandlerError<T>> error =
            shared_handler->OnListen(method_call->arguments(), std::move(sink));
        if (error) {
          result = codec->EncodeErrorEnvelope(
              error->error_code, error->error_message, error->error_details);
        } else {
          result = codec->EncodeSuccessEnvelope();
        }
        reply(result->data(), result->size());
      } else if (method.compare(kOnCancelMethod) == 0) {
        std::unique_ptr<std::vector<uint8_t>> result;
        if (is_listening_) {
          std::unique_ptr<StreamHandlerError<T>> error =
              shared_handler->OnCancel(method_call->arguments());
          if (error) {
            result = codec->EncodeErrorEnvelope(
                error->error_code, error->error_message, error->error_details);
          } else {
            result = codec->EncodeSuccessEnvelope();
          }
          is_listening_ = false;
        } else {
          result = codec->EncodeErrorEnvelope(
              "error", "No active stream to cancel", nullptr);
        }
        reply(result->data(), result->size());
      } else {
        reply(nullptr, 0);
      }
    };
    messenger_->SetMessageHandler(name_, std::move(binary_handler));
  }

 private:
  class EventSinkImplementation : public EventSink<T> {
   public:
    EventSinkImplementation(const BinaryMessenger* messenger,
                            const std::string& name,
                            const MethodCodec<T>* codec)
        : messenger_(messenger), name_(name), codec_(codec) {}
    ~EventSinkImplementation() = default;

    // Prevent copying.
    EventSinkImplementation(EventSinkImplementation const&) = delete;
    EventSinkImplementation& operator=(EventSinkImplementation const&) = delete;

   private:
    const BinaryMessenger* messenger_;
    const std::string name_;
    const MethodCodec<T>* codec_;

   protected:
    void SuccessInternal(const T* event = nullptr) override {
      auto result = codec_->EncodeSuccessEnvelope(event);
      messenger_->Send(name_, result->data(), result->size());
    }

    void ErrorInternal(const std::string& error_code,
                       const std::string& error_message,
                       const T* error_details) override {
      auto result =
          codec_->EncodeErrorEnvelope(error_code, error_message, error_details);
      messenger_->Send(name_, result->data(), result->size());
    }

    void EndOfStreamInternal() override { messenger_->Send(name_, nullptr, 0); }
  };

  BinaryMessenger* messenger_;
  const std::string name_;
  const MethodCodec<T>* codec_;
  bool is_listening_;
};

}  // namespace flutter

#endif  // FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_EVENT_CHANNEL_H_
