package dial

import (
	"context"
	"github.com/exchain/go-exchain/exchain/exchainclient"

	"github.com/ethereum/go-ethereum/log"
)

// L2EndpointProvider is an interface for providing a RollupClient and l2 eth client
// It manages the lifecycle of the RollupClient and eth client for callers
// It does this by extending the RollupProvider interface to add the ability to get an EthClient
type L2EndpointProvider interface {
	RollupProvider
	// EthClient(ctx) returns the underlying ethclient pointing to the L2 execution node.
	// Note: ctx should be a lifecycle context without an attached timeout as client selection may involve
	// multiple network operations, specifically in the case of failover.
	EthClient(ctx context.Context) (ExchainClientInterface, error)
}

// StaticL2EndpointProvider is a L2EndpointProvider that always returns the same static RollupClient and eth client
// It is meant for scenarios where a single, unchanging (L2 rollup node, L2 execution node) pair is used
type StaticL2EndpointProvider struct {
	StaticL2RollupProvider
	l2Client *exchainclient.ExClient
}

func NewStaticL2EndpointProvider(ctx context.Context, log log.Logger, l2Url string, rollupClientUrl string) (*StaticL2EndpointProvider, error) {
	cli, err := exchainclient.NewExClient(l2Url)
	if err != nil {
		return nil, err
	}

	rollupProvider, err := NewStaticL2RollupProvider(ctx, log, rollupClientUrl)
	if err != nil {
		return nil, err
	}
	return &StaticL2EndpointProvider{
		StaticL2RollupProvider: *rollupProvider,
		l2Client:               cli,
	}, nil
}

func (p *StaticL2EndpointProvider) EthClient(context.Context) (ExchainClientInterface, error) {
	return p.l2Client, nil
}

func (p *StaticL2EndpointProvider) Close() {
	if p.l2Client != nil {
		p.l2Client.Close()
	}
	p.StaticL2RollupProvider.Close()
}
