// Licensed to Apache Software Foundation (ASF) under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Apache Software Foundation (ASF) licenses this file to you 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 grpc

import (
	"context"
	"fmt"

	"github.com/sirupsen/logrus"
	"google.golang.org/grpc"
	"google.golang.org/grpc/grpclog"

	"github.com/apache/skywalking-satellite/internal/pkg/config"
	"github.com/apache/skywalking-satellite/internal/pkg/log"
	"github.com/apache/skywalking-satellite/plugins/client/api"
	"github.com/apache/skywalking-satellite/plugins/client/grpc/resolvers"
)

const Name = "grpc-client"

type Client struct {
	config.CommonFields
	// server finder config
	ServerFinderConfig resolvers.ServerFinderConfig `mapstructure:",squash"`
	// config
	EnableTLS          bool   `mapstructure:"enable_TLS"`           // Enable TLS connect to server
	ClientPemPath      string `mapstructure:"client_pem_path"`      // The file path of client.pem. The config only works when opening the TLS switch.
	ClientKeyPath      string `mapstructure:"client_key_path"`      // The file path of client.key. The config only works when opening the TLS switch.
	CaPemPath          string `mapstructure:"ca_pem_path"`          // The file path oca.pem. The config only works when opening the TLS switch.
	InsecureSkipVerify bool   `mapstructure:"insecure_skip_verify"` // Controls whether a client verifies the server's certificate chain and host name.
	Authentication     string `mapstructure:"authentication"`       // The auth value when send request
	CheckPeriod        int    `mapstructure:"check_period"`         // How frequently to check the connection

	// components
	status    api.ClientStatus
	client    *grpc.ClientConn
	listeners []chan<- api.ClientStatus
	ctx       context.Context    // Parent ctx
	cancel    context.CancelFunc // Parent ctx cancel function
}

func (c *Client) Name() string {
	return Name
}

func (c *Client) Description() string {
	return "The gRPC client is a sharing plugin to keep connection with the gRPC server and delivery the data to it."
}

func (c *Client) DefaultConfig() string {
	return `
# The gRPC server address (default localhost:11800), multiple addresses are split by ",".
server_addr: localhost:11800

# The TLS switch (default false).
enable_TLS: false

# The file path of client.pem. The config only works when opening the TLS switch.
client_pem_path: ""

# The file path of client.key. The config only works when opening the TLS switch.
client_key_path: ""

# The file path oca.pem. The config only works when opening the TLS switch.
ca_pem_path: ""

# InsecureSkipVerify controls whether a client verifies the server's certificate chain and host name.
insecure_skip_verify: true

# The auth value when send request
authentication: ""

# How frequently to check the connection
check_period: 5
`
}

func (c *Client) Prepare() error {
	// config
	cfg, err := c.loadConfig()
	if err != nil {
		return fmt.Errorf("cannot init the grpc client: %v", err)
	}

	// logger
	grpclog.SetLoggerV2(&logrusGrpcLoggerV2{log.Logger.WithFields(logrus.Fields{
		"client_name": Name,
	})})

	// server address resolver
	resolvers.RegisterAllGrpcResolvers()

	// connect to server
	target, err := resolvers.BuildTarget(&c.ServerFinderConfig)
	if err != nil {
		return fmt.Errorf("cannot build grpc target: %v", err)
	}
	client, err := grpc.Dial(target, *cfg...)
	if err != nil {
		return fmt.Errorf("cannot connect to grpc server: %v", err)
	}

	c.client = client
	c.status = api.Connected
	c.ctx, c.cancel = context.WithCancel(context.Background())
	c.listeners = make([]chan<- api.ClientStatus, 0)
	return nil
}

func (c *Client) Close() error {
	c.cancel()
	defer log.Logger.Info("grpc client is closed")
	return c.client.Close()
}

func (c *Client) GetConnectedClient() interface{} {
	return c.client
}

func (c *Client) RegisterListener(listener chan<- api.ClientStatus) {
	c.listeners = append(c.listeners, listener)
}

func (c *Client) Start() error {
	go c.snifferChannelStatus()
	return nil
}

// grpc log adaptor
type logrusGrpcLoggerV2 struct {
	*logrus.Entry
}

func (l *logrusGrpcLoggerV2) V(level int) bool {
	return l.Logger.IsLevelEnabled(logrus.Level(level))
}
