/*
 *
 *    Copyright (c) 2020-2025 Project CHIP Authors
 *    Copyright (c) 2013-2017 Nest Labs, Inc.
 *
 *    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
 *
 *        http://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.
 */

/**
 * Provides access to UDP (and optionally TCP) EndPointManager.
 */

#pragma once

#include <inet/EndPointBasis.h>
#include <inet/InetError.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/ObjectLifeCycle.h>
#include <lib/support/Pool.h>
#include <lib/support/ReferenceCountedPtr.h>
#include <platform/LockTracker.h>
#include <system/SystemLayer.h>
#include <system/SystemStats.h>

#include <stdint.h>

namespace chip {
namespace Inet {

template <typename EndPointType>
class EndPointDeletor;

/**
 * Template providing traits for EndPoint types used by EndPointManager.
 *
 * Instances must define:
 *      static constexpr const char * kName;
 *      static constexpr int kSystemStatsKey;
 */
template <class EndPointType>
struct EndPointProperties;

template <class EndPointType>
class EndPointHandle : public ReferenceCountedPtr<EndPointType>
{
public:
    using ReferenceCountedPtr<EndPointType>::ReferenceCountedPtr;

    // For printing
    inline operator const void *() const { return this->mRefCounted; }
};

/**
 * Manage creating, deletion, and iteration of Inet::EndPoint types.
 */
template <class EndPointType>
class EndPointManager
{
public:
    using EndPoint            = EndPointType;
    using TypedEndPointHandle = EndPointHandle<EndPoint>;
    using EndPointVisitor     = Loop (*)(const TypedEndPointHandle &);

    EndPointManager() {}
    virtual ~EndPointManager() { VerifyOrDie(mLayerState.Destroy()); }

    CHIP_ERROR Init(System::Layer & systemLayer)
    {
        RegisterLayerErrorFormatter();
        VerifyOrReturnError(mLayerState.SetInitializing(), CHIP_ERROR_INCORRECT_STATE);
        VerifyOrReturnError(systemLayer.IsInitialized(), CHIP_ERROR_INCORRECT_STATE);
        mSystemLayer = &systemLayer;
        mLayerState.SetInitialized();
        return CHIP_NO_ERROR;
    }

    void Shutdown()
    {
        // Return to uninitialized state to permit re-initialization.
        mLayerState.ResetFromInitialized();
        mSystemLayer = nullptr;
    }

    System::Layer & SystemLayer() const { return *mSystemLayer; }

    CHIP_ERROR NewEndPoint(TypedEndPointHandle & retEndPoint)
    {
        assertChipStackLockedByCurrentThread();
        VerifyOrReturnError(mLayerState.IsInitialized(), CHIP_ERROR_INCORRECT_STATE);

        retEndPoint = std::move(CreateEndPoint());
        if (retEndPoint.IsNull())
        {
            ChipLogError(Inet, "%s endpoint pool FULL", EndPointProperties<EndPointType>::kName);
            return CHIP_ERROR_ENDPOINT_POOL_FULL;
        }

        SYSTEM_STATS_INCREMENT(EndPointProperties<EndPointType>::kSystemStatsKey);
        return CHIP_NO_ERROR;
    }

    virtual Loop ForEachEndPoint(const EndPointVisitor visitor) = 0;

protected:
    friend class EndPointDeletor<EndPointType>;
    friend class EndPointHandle<EndPointType>;
    friend class EndPointBasis<EndPointType>;
    friend EndPointType;

    virtual TypedEndPointHandle CreateEndPoint() = 0;

    virtual void ReleaseEndPoint(EndPoint * endPoint) = 0;

    void DeleteEndPoint(EndPoint * endPoint)
    {
        SYSTEM_STATS_DECREMENT(EndPointProperties<EndPointType>::kSystemStatsKey);
        ReleaseEndPoint(endPoint);
    }

private:
    ObjectLifeCycle mLayerState;
    System::Layer * mSystemLayer;
};

template <typename EndPointImpl>
class EndPointManagerImplPool : public EndPointManager<typename EndPointImpl::EndPoint>
{
public:
    using Manager             = EndPointManager<typename EndPointImpl::EndPoint>;
    using EndPoint            = typename EndPointImpl::EndPoint;
    using TypedEndPointHandle = typename Manager::TypedEndPointHandle;

    EndPointManagerImplPool()           = default;
    ~EndPointManagerImplPool() override = default;

    TypedEndPointHandle CreateEndPoint() override { return sEndPointPool.CreateObject(*this); }
    Loop ForEachEndPoint(const typename Manager::EndPointVisitor visitor) override
    {
        return sEndPointPool.ForEachActiveObject([&](EndPoint * endPoint) -> Loop {
            TypedEndPointHandle handle(endPoint);
            return visitor(handle);
        });
    }

private:
    void ReleaseEndPoint(EndPoint * endPoint) override { sEndPointPool.ReleaseObject(static_cast<EndPointImpl *>(endPoint)); }

    ObjectPool<EndPointImpl, EndPointProperties<EndPoint>::kNumEndPoints> sEndPointPool;
};

class TCPEndPoint;
class UDPEndPoint;

} // namespace Inet
} // namespace chip
