/*
 * Copyright 2021 CloudWeGo Authors
 *
 * 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.
 */

package proxy

import (
	"context"
	"net"

	"github.com/cloudwego/kitex/pkg/discovery"
	"github.com/cloudwego/kitex/pkg/endpoint"
	"github.com/cloudwego/kitex/pkg/loadbalance"
	"github.com/cloudwego/kitex/pkg/remote"
	"github.com/cloudwego/kitex/pkg/rpcinfo"
)

// Config contains basic components used in service discovery process.
type Config struct {
	ServerInfo   *rpcinfo.EndpointBasicInfo
	Resolver     discovery.Resolver
	Balancer     loadbalance.Loadbalancer
	Pool         remote.ConnPool
	FixedTargets string // A comma separated list of host ports that user specify to use.
	RPCConfig    rpcinfo.RPCConfig
}

// ForwardProxy manages the service discovery, load balance and connection pooling processes.
type ForwardProxy interface {
	// Configure is provided to initialize the proxy.
	Configure(*Config) error

	// ResolveProxyInstance set instance for remote endpoint.
	ResolveProxyInstance(ctx context.Context) error
}

// WithMiddleware provides function to customize proxy middleware implementation.
type WithMiddleware interface {
	// ProxyMiddleware returns a middleware which implement proxy logic.
	ProxyMiddleware() endpoint.Middleware
}

// ReverseProxy replaces the listen address with another one.
type ReverseProxy interface {
	Replace(net.Addr) (net.Addr, error)
}

// Deprecated: BackwardProxy is deprecated, use ReverseProxy instead.
type BackwardProxy = ReverseProxy

// ContextHandler is to handle context info, it just be used for passing params when client/server initialization.
// Eg: Customized endpoint.MiddlewareBuilder need get init information to judge
// if it is necessary to add the middleware into the call chain.
type ContextHandler interface {
	HandleContext(context.Context) context.Context
}
