/*
 *
 * Copyright 2020 gRPC 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 xds contains an implementation of the xDS suite of protocols, to be
// used by gRPC client and server applications.
//
// On the client-side, users simply need to import this package to get all xDS
// functionality. On the server-side, users need to use the GRPCServer type
// exported by this package instead of the regular grpc.Server.
//
// See https://github.com/grpc/grpc-go/tree/master/examples/features/xds for
// example.
//
// Experimental
//
// Notice: All APIs in this package are experimental and may be removed in a
// later release.
package xds

import (
	"fmt"

	v3statusgrpc "github.com/envoyproxy/go-control-plane/envoy/service/status/v3"
	"google.golang.org/grpc"
	internaladmin "google.golang.org/grpc/internal/admin"
	"google.golang.org/grpc/xds/csds"

	_ "google.golang.org/grpc/credentials/tls/certprovider/pemfile" // Register the file watcher certificate provider plugin.
	_ "google.golang.org/grpc/xds/internal/balancer"                // Register the balancers.
	_ "google.golang.org/grpc/xds/internal/client/v2"               // Register the v2 xDS API client.
	_ "google.golang.org/grpc/xds/internal/client/v3"               // Register the v3 xDS API client.
	_ "google.golang.org/grpc/xds/internal/httpfilter/fault"        // Register the fault injection filter.
	_ "google.golang.org/grpc/xds/internal/resolver"                // Register the xds_resolver.
)

func init() {
	internaladmin.AddService(func(registrar grpc.ServiceRegistrar) (func(), error) {
		var grpcServer *grpc.Server
		switch ss := registrar.(type) {
		case *grpc.Server:
			grpcServer = ss
		case *GRPCServer:
			sss, ok := ss.gs.(*grpc.Server)
			if !ok {
				logger.Warningf("grpc server within xds.GRPCServer is not *grpc.Server, CSDS will not be registered")
				return nil, nil
			}
			grpcServer = sss
		default:
			// Returning an error would cause the top level admin.Register() to
			// fail. Log a warning instead.
			logger.Warningf("server to register service on is neither a *grpc.Server or a *xds.GRPCServer, CSDS will not be registered")
			return nil, nil
		}

		csdss, err := csds.NewClientStatusDiscoveryServer()
		if err != nil {
			return nil, fmt.Errorf("failed to create csds server: %v", err)
		}
		v3statusgrpc.RegisterClientStatusDiscoveryServiceServer(grpcServer, csdss)
		return csdss.Close, nil
	})
}
