// 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_METHOD_CHANNEL_H_
#define FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_METHOD_CHANNEL_H_

#include <iostream>
#include <string>

#include "binary_messenger.h"
#include "engine_method_result.h"
#include "method_call.h"
#include "method_codec.h"
#include "method_result.h"

namespace flutter {

// A handler for receiving a method call from the Flutter engine.
//
// Implementations must asynchronously call exactly one of the methods on
// |result| to indicate the result of the method call.
template <typename T>
using MethodCallHandler =
    std::function<void(const MethodCall<T>& call,
                       std::unique_ptr<MethodResult<T>> result)>;

// A channel for communicating with the Flutter engine using invocation of
// asynchronous methods.
template <typename T>
class MethodChannel {
 public:
  // Creates an instance that sends and receives method calls on the channel
  // named |name|, encoded with |codec| and dispatched via |messenger|.
  MethodChannel(BinaryMessenger* messenger,
                const std::string& name,
                const MethodCodec<T>* codec)
      : messenger_(messenger), name_(name), codec_(codec) {}

  ~MethodChannel() = default;

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

  // Sends a message to the Flutter engine on this channel.
  //
  // If |result| is provided, one of its methods will be invoked with the
  // response from the engine.
  void InvokeMethod(const std::string& method,
                    std::unique_ptr<T> arguments,
                    std::unique_ptr<MethodResult<T>> result = nullptr) {
    MethodCall<T> method_call(method, std::move(arguments));
    std::unique_ptr<std::vector<uint8_t>> message =
        codec_->EncodeMethodCall(method_call);
    if (!result) {
      messenger_->Send(name_, message->data(), message->size(), nullptr);
      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<MethodResult<T>> shared_result(result.release());
    const auto* codec = codec_;
    std::string channel_name = name_;
    BinaryReply reply_handler = [shared_result, codec, channel_name](
                                    const uint8_t* reply, size_t reply_size) {
      if (reply_size == 0) {
        shared_result->NotImplemented();
        return;
      }
      // Use this channel's codec to decode and handle the
      // reply.
      bool decoded = codec->DecodeAndProcessResponseEnvelope(
          reply, reply_size, shared_result.get());
      if (!decoded) {
        std::cerr << "Unable to decode reply to method "
                     "invocation on channel "
                  << channel_name << std::endl;
        shared_result->NotImplemented();
      }
    };

    messenger_->Send(name_, message->data(), message->size(),
                     std::move(reply_handler));
  }

  // Registers a handler that should be called any time a method call is
  // received on this channel. A null handler will remove any previous handler.
  //
  // Note that the MethodChannel does not own the handler, and will not
  // unregister it on destruction, so the caller is responsible for
  // unregistering explicitly if it should no longer be called.
  void SetMethodCallHandler(MethodCallHandler<T> handler) const {
    if (!handler) {
      messenger_->SetMessageHandler(name_, nullptr);
      return;
    }
    const auto* codec = codec_;
    std::string channel_name = name_;
    BinaryMessageHandler binary_handler = [handler, codec, channel_name](
                                              const uint8_t* message,
                                              size_t message_size,
                                              BinaryReply reply) {
      // Use this channel's codec to decode the call and build a result handler.
      auto result =
          std::make_unique<EngineMethodResult<T>>(std::move(reply), codec);
      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;
        result->NotImplemented();
        return;
      }
      handler(*method_call, std::move(result));
    };
    messenger_->SetMessageHandler(name_, std::move(binary_handler));
  }

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

}  // namespace flutter

#endif  // FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_METHOD_CHANNEL_H_
