//
// Copyright 2016 The ANGLE 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.
//
// signal_utils:
//   Helper classes for tracking dependent state changes between objects.
//   These changes are signaled to the dependent class via channels.

#ifndef LIBANGLE_SIGNAL_UTILS_H_
#define LIBANGLE_SIGNAL_UTILS_H_

#include <set>

#include "common/angleutils.h"
#include "common/debug.h"

namespace angle
{

// Interface that the depending class inherits from.
template <typename ChannelID = uint32_t, typename... MessageT>
class SignalReceiver
{
  public:
    virtual ~SignalReceiver() = default;
    virtual void signal(ChannelID channelID, MessageT... message) = 0;
};

template <typename ChannelID, typename... MessageT>
class ChannelBinding;

// The host class owns the channel. It uses the channel to fire signals to the receiver.
template <typename ChannelID = uint32_t, typename... MessageT>
class BroadcastChannel final : NonCopyable
{
  public:
    BroadcastChannel();
    ~BroadcastChannel();

    void signal(MessageT... message) const;

    void reset();

  private:
    // Only the ChannelBinding class should add or remove receivers.
    friend class ChannelBinding<ChannelID, MessageT...>;
    void addReceiver(ChannelBinding<ChannelID, MessageT...> *receiver);
    void removeReceiver(ChannelBinding<ChannelID, MessageT...> *receiver);

    std::vector<ChannelBinding<ChannelID, MessageT...> *> mReceivers;
};

template <typename ChannelID, typename... MessageT>
BroadcastChannel<ChannelID, MessageT...>::BroadcastChannel()
{
}

template <typename ChannelID, typename... MessageT>
BroadcastChannel<ChannelID, MessageT...>::~BroadcastChannel()
{
    reset();
}

template <typename ChannelID, typename... MessageT>
void BroadcastChannel<ChannelID, MessageT...>::addReceiver(
    ChannelBinding<ChannelID, MessageT...> *receiver)
{
    ASSERT(std::find(mReceivers.begin(), mReceivers.end(), receiver) == mReceivers.end());
    mReceivers.push_back(receiver);
}

template <typename ChannelID, typename... MessageT>
void BroadcastChannel<ChannelID, MessageT...>::removeReceiver(
    ChannelBinding<ChannelID, MessageT...> *receiver)
{
    auto iter = std::find(mReceivers.begin(), mReceivers.end(), receiver);
    ASSERT(iter != mReceivers.end());
    mReceivers.erase(iter);
}

template <typename ChannelID, typename... MessageT>
void BroadcastChannel<ChannelID, MessageT...>::signal(MessageT... message) const
{
    if (mReceivers.empty())
        return;

    for (const auto *receiver : mReceivers)
    {
        receiver->signal(message...);
    }
}

template <typename ChannelID, typename... MessageT>
void BroadcastChannel<ChannelID, MessageT...>::reset()
{
    for (auto receiver : mReceivers)
    {
        receiver->onChannelClosed();
    }
    mReceivers.clear();
}

// The dependent class keeps bindings to the host's BroadcastChannel.
template <typename ChannelID = uint32_t, typename... MessageT>
class ChannelBinding final
{
  public:
    ChannelBinding(SignalReceiver<ChannelID, MessageT...> *receiver, ChannelID channelID);
    ~ChannelBinding();
    ChannelBinding(const ChannelBinding &other) = default;
    ChannelBinding &operator=(const ChannelBinding &other) = default;

    void bind(BroadcastChannel<ChannelID, MessageT...> *channel);
    void reset();
    void signal(MessageT... message) const;
    void onChannelClosed();

  private:
    BroadcastChannel<ChannelID, MessageT...> *mChannel;
    SignalReceiver<ChannelID, MessageT...> *mReceiver;
    ChannelID mChannelID;
};

template <typename ChannelID, typename... MessageT>
ChannelBinding<ChannelID, MessageT...>::ChannelBinding(
    SignalReceiver<ChannelID, MessageT...> *receiver,
    ChannelID channelID)
    : mChannel(nullptr), mReceiver(receiver), mChannelID(channelID)
{
    ASSERT(receiver);
}

template <typename ChannelID, typename... MessageT>
ChannelBinding<ChannelID, MessageT...>::~ChannelBinding()
{
    reset();
}

template <typename ChannelID, typename... MessageT>
void ChannelBinding<ChannelID, MessageT...>::bind(BroadcastChannel<ChannelID, MessageT...> *channel)
{
    ASSERT(mReceiver);
    if (mChannel)
    {
        mChannel->removeReceiver(this);
    }

    mChannel = channel;

    if (mChannel)
    {
        mChannel->addReceiver(this);
    }
}

template <typename ChannelID, typename... MessageT>
void ChannelBinding<ChannelID, MessageT...>::reset()
{
    bind(nullptr);
}

template <typename ChannelID, typename... MessageT>
void ChannelBinding<ChannelID, MessageT...>::signal(MessageT... message) const
{
    mReceiver->signal(mChannelID, message...);
}

template <typename ChannelID, typename... MessageT>
void ChannelBinding<ChannelID, MessageT...>::onChannelClosed()
{
    mChannel = nullptr;
}

}  // namespace angle

#endif  // LIBANGLE_SIGNAL_UTILS_H_
