/*
 * Licensed to the 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.
 * The 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.
 */

// Code generated by protoc-gen-go-triple. DO NOT EDIT.
// versions:
// - protoc-gen-go-triple v1.0.8
// - protoc             v3.15.5
// source: internal/proto/greet.proto

package greet

import (
	context "context"
	fmt "fmt"
)

import (
	grpc_go "github.com/dubbogo/grpc-go"
	codes "github.com/dubbogo/grpc-go/codes"
	metadata "github.com/dubbogo/grpc-go/metadata"
	status "github.com/dubbogo/grpc-go/status"

	common "github.com/dubbogo/triple/pkg/common"
	constant "github.com/dubbogo/triple/pkg/common/constant"
	triple "github.com/dubbogo/triple/pkg/triple"
)

import (
	constant1 "dubbo.apache.org/dubbo-go/v3/common/constant"
	protocol "dubbo.apache.org/dubbo-go/v3/protocol"
	dubbo3 "dubbo.apache.org/dubbo-go/v3/protocol/dubbo3"
	invocation "dubbo.apache.org/dubbo-go/v3/protocol/invocation"
)

// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
const _ = grpc_go.SupportPackageIsVersion7

// GreetServiceClient is the client API for GreetService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type GreetServiceClient interface {
	Greet(ctx context.Context, in *GreetRequest, opts ...grpc_go.CallOption) (*GreetResponse, common.ErrorWithAttachment)
	GreetStream(ctx context.Context, opts ...grpc_go.CallOption) (GreetService_GreetStreamClient, error)
	GreetClientStream(ctx context.Context, opts ...grpc_go.CallOption) (GreetService_GreetClientStreamClient, error)
	GreetServerStream(ctx context.Context, in *GreetServerStreamRequest, opts ...grpc_go.CallOption) (GreetService_GreetServerStreamClient, error)
}

type greetServiceClient struct {
	cc *triple.TripleConn
}

type GreetServiceClientImpl struct {
	Greet             func(ctx context.Context, in *GreetRequest) (*GreetResponse, error)
	GreetStream       func(ctx context.Context) (GreetService_GreetStreamClient, error)
	GreetClientStream func(ctx context.Context) (GreetService_GreetClientStreamClient, error)
	GreetServerStream func(ctx context.Context, in *GreetServerStreamRequest) (GreetService_GreetServerStreamClient, error)
}

func (c *GreetServiceClientImpl) GetDubboStub(cc *triple.TripleConn) GreetServiceClient {
	return NewGreetServiceClient(cc)
}

func (c *GreetServiceClientImpl) XXX_InterfaceName() string {
	return "greet.GreetService"
}

func NewGreetServiceClient(cc *triple.TripleConn) GreetServiceClient {
	return &greetServiceClient{cc}
}

func (c *greetServiceClient) Greet(ctx context.Context, in *GreetRequest, opts ...grpc_go.CallOption) (*GreetResponse, common.ErrorWithAttachment) {
	out := new(GreetResponse)
	interfaceKey := ctx.Value(constant.InterfaceKey).(string)
	return out, c.cc.Invoke(ctx, "/"+interfaceKey+"/Greet", in, out)
}

func (c *greetServiceClient) GreetStream(ctx context.Context, opts ...grpc_go.CallOption) (GreetService_GreetStreamClient, error) {
	interfaceKey := ctx.Value(constant.InterfaceKey).(string)
	stream, err := c.cc.NewStream(ctx, "/"+interfaceKey+"/GreetStream", opts...)
	if err != nil {
		return nil, err
	}
	x := &greetServiceGreetStreamClient{stream}
	return x, nil
}

type GreetService_GreetStreamClient interface {
	Send(*GreetStreamRequest) error
	Recv() (*GreetStreamResponse, error)
	grpc_go.ClientStream
}

type greetServiceGreetStreamClient struct {
	grpc_go.ClientStream
}

func (x *greetServiceGreetStreamClient) Send(m *GreetStreamRequest) error {
	return x.ClientStream.SendMsg(m)
}

func (x *greetServiceGreetStreamClient) Recv() (*GreetStreamResponse, error) {
	m := new(GreetStreamResponse)
	if err := x.ClientStream.RecvMsg(m); err != nil {
		return nil, err
	}
	return m, nil
}

func (c *greetServiceClient) GreetClientStream(ctx context.Context, opts ...grpc_go.CallOption) (GreetService_GreetClientStreamClient, error) {
	interfaceKey := ctx.Value(constant.InterfaceKey).(string)
	stream, err := c.cc.NewStream(ctx, "/"+interfaceKey+"/GreetClientStream", opts...)
	if err != nil {
		return nil, err
	}
	x := &greetServiceGreetClientStreamClient{stream}
	return x, nil
}

type GreetService_GreetClientStreamClient interface {
	Send(*GreetClientStreamRequest) error
	CloseAndRecv() (*GreetClientStreamResponse, error)
	grpc_go.ClientStream
}

type greetServiceGreetClientStreamClient struct {
	grpc_go.ClientStream
}

func (x *greetServiceGreetClientStreamClient) Send(m *GreetClientStreamRequest) error {
	return x.ClientStream.SendMsg(m)
}

func (x *greetServiceGreetClientStreamClient) CloseAndRecv() (*GreetClientStreamResponse, error) {
	if err := x.ClientStream.CloseSend(); err != nil {
		return nil, err
	}
	m := new(GreetClientStreamResponse)
	if err := x.ClientStream.RecvMsg(m); err != nil {
		return nil, err
	}
	return m, nil
}

func (c *greetServiceClient) GreetServerStream(ctx context.Context, in *GreetServerStreamRequest, opts ...grpc_go.CallOption) (GreetService_GreetServerStreamClient, error) {
	interfaceKey := ctx.Value(constant.InterfaceKey).(string)
	stream, err := c.cc.NewStream(ctx, "/"+interfaceKey+"/GreetServerStream", opts...)
	if err != nil {
		return nil, err
	}
	x := &greetServiceGreetServerStreamClient{stream}
	if err := x.ClientStream.SendMsg(in); err != nil {
		return nil, err
	}
	if err := x.ClientStream.CloseSend(); err != nil {
		return nil, err
	}
	return x, nil
}

type GreetService_GreetServerStreamClient interface {
	Recv() (*GreetServerStreamResponse, error)
	grpc_go.ClientStream
}

type greetServiceGreetServerStreamClient struct {
	grpc_go.ClientStream
}

func (x *greetServiceGreetServerStreamClient) Recv() (*GreetServerStreamResponse, error) {
	m := new(GreetServerStreamResponse)
	if err := x.ClientStream.RecvMsg(m); err != nil {
		return nil, err
	}
	return m, nil
}

// GreetServiceServer is the server API for GreetService service.
// All implementations must embed UnimplementedGreetServiceServer
// for forward compatibility
type GreetServiceServer interface {
	Greet(context.Context, *GreetRequest) (*GreetResponse, error)
	GreetStream(GreetService_GreetStreamServer) error
	GreetClientStream(GreetService_GreetClientStreamServer) error
	GreetServerStream(*GreetServerStreamRequest, GreetService_GreetServerStreamServer) error
	mustEmbedUnimplementedGreetServiceServer()
}

// UnimplementedGreetServiceServer must be embedded to have forward compatible implementations.
type UnimplementedGreetServiceServer struct {
	proxyImpl protocol.Invoker
}

func (UnimplementedGreetServiceServer) Greet(context.Context, *GreetRequest) (*GreetResponse, error) {
	return nil, status.Errorf(codes.Unimplemented, "method Greet not implemented")
}
func (UnimplementedGreetServiceServer) GreetStream(GreetService_GreetStreamServer) error {
	return status.Errorf(codes.Unimplemented, "method GreetStream not implemented")
}
func (UnimplementedGreetServiceServer) GreetClientStream(GreetService_GreetClientStreamServer) error {
	return status.Errorf(codes.Unimplemented, "method GreetClientStream not implemented")
}
func (UnimplementedGreetServiceServer) GreetServerStream(*GreetServerStreamRequest, GreetService_GreetServerStreamServer) error {
	return status.Errorf(codes.Unimplemented, "method GreetServerStream not implemented")
}
func (s *UnimplementedGreetServiceServer) XXX_SetProxyImpl(impl protocol.Invoker) {
	s.proxyImpl = impl
}

func (s *UnimplementedGreetServiceServer) XXX_GetProxyImpl() protocol.Invoker {
	return s.proxyImpl
}

func (s *UnimplementedGreetServiceServer) XXX_ServiceDesc() *grpc_go.ServiceDesc {
	return &GreetService_ServiceDesc
}
func (s *UnimplementedGreetServiceServer) XXX_InterfaceName() string {
	return "greet.GreetService"
}

func (UnimplementedGreetServiceServer) mustEmbedUnimplementedGreetServiceServer() {}

// UnsafeGreetServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to GreetServiceServer will
// result in compilation errors.
type UnsafeGreetServiceServer interface {
	mustEmbedUnimplementedGreetServiceServer()
}

func RegisterGreetServiceServer(s grpc_go.ServiceRegistrar, srv GreetServiceServer) {
	s.RegisterService(&GreetService_ServiceDesc, srv)
}

func _GreetService_Greet_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc_go.UnaryServerInterceptor) (interface{}, error) {
	in := new(GreetRequest)
	if err := dec(in); err != nil {
		return nil, err
	}
	base := srv.(dubbo3.Dubbo3GrpcService)
	args := []interface{}{}
	args = append(args, in)
	md, _ := metadata.FromIncomingContext(ctx)
	invAttachment := make(map[string]interface{}, len(md))
	for k, v := range md {
		invAttachment[k] = v
	}
	invo := invocation.NewRPCInvocation("Greet", args, invAttachment)
	if interceptor == nil {
		result := base.XXX_GetProxyImpl().Invoke(ctx, invo)
		return result, result.Error()
	}
	info := &grpc_go.UnaryServerInfo{
		Server:     srv,
		FullMethod: ctx.Value("XXX_TRIPLE_GO_INTERFACE_NAME").(string),
	}
	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
		result := base.XXX_GetProxyImpl().Invoke(ctx, invo)
		return result, result.Error()
	}
	return interceptor(ctx, in, info, handler)
}

func _GreetService_GreetStream_Handler(srv interface{}, stream grpc_go.ServerStream) error {
	_, ok := srv.(dubbo3.Dubbo3GrpcService)
	ctx := stream.Context()
	md, _ := metadata.FromIncomingContext(ctx)
	invAttachment := make(map[string]interface{}, len(md))
	for k, v := range md {
		invAttachment[k] = v
	}
	stream.(grpc_go.CtxSetterStream).SetContext(context.WithValue(ctx, constant1.AttachmentKey, invAttachment))
	invo := invocation.NewRPCInvocation("GreetStream", nil, nil)
	if !ok {
		fmt.Println(invo)
		return nil
	}
	return srv.(GreetServiceServer).GreetStream(&greetServiceGreetStreamServer{stream})
}

type GreetService_GreetStreamServer interface {
	Send(*GreetStreamResponse) error
	Recv() (*GreetStreamRequest, error)
	grpc_go.ServerStream
}

type greetServiceGreetStreamServer struct {
	grpc_go.ServerStream
}

func (x *greetServiceGreetStreamServer) Send(m *GreetStreamResponse) error {
	return x.ServerStream.SendMsg(m)
}

func (x *greetServiceGreetStreamServer) Recv() (*GreetStreamRequest, error) {
	m := new(GreetStreamRequest)
	if err := x.ServerStream.RecvMsg(m); err != nil {
		return nil, err
	}
	return m, nil
}

func _GreetService_GreetClientStream_Handler(srv interface{}, stream grpc_go.ServerStream) error {
	_, ok := srv.(dubbo3.Dubbo3GrpcService)
	ctx := stream.Context()
	md, _ := metadata.FromIncomingContext(ctx)
	invAttachment := make(map[string]interface{}, len(md))
	for k, v := range md {
		invAttachment[k] = v
	}
	stream.(grpc_go.CtxSetterStream).SetContext(context.WithValue(ctx, constant1.AttachmentKey, invAttachment))
	invo := invocation.NewRPCInvocation("GreetClientStream", nil, nil)
	if !ok {
		fmt.Println(invo)
		return nil
	}
	return srv.(GreetServiceServer).GreetClientStream(&greetServiceGreetClientStreamServer{stream})
}

type GreetService_GreetClientStreamServer interface {
	SendAndClose(*GreetClientStreamResponse) error
	Recv() (*GreetClientStreamRequest, error)
	grpc_go.ServerStream
}

type greetServiceGreetClientStreamServer struct {
	grpc_go.ServerStream
}

func (x *greetServiceGreetClientStreamServer) SendAndClose(m *GreetClientStreamResponse) error {
	return x.ServerStream.SendMsg(m)
}

func (x *greetServiceGreetClientStreamServer) Recv() (*GreetClientStreamRequest, error) {
	m := new(GreetClientStreamRequest)
	if err := x.ServerStream.RecvMsg(m); err != nil {
		return nil, err
	}
	return m, nil
}

func _GreetService_GreetServerStream_Handler(srv interface{}, stream grpc_go.ServerStream) error {
	_, ok := srv.(dubbo3.Dubbo3GrpcService)
	ctx := stream.Context()
	md, _ := metadata.FromIncomingContext(ctx)
	invAttachment := make(map[string]interface{}, len(md))
	for k, v := range md {
		invAttachment[k] = v
	}
	stream.(grpc_go.CtxSetterStream).SetContext(context.WithValue(ctx, constant1.AttachmentKey, invAttachment))
	invo := invocation.NewRPCInvocation("GreetServerStream", nil, nil)
	if !ok {
		fmt.Println(invo)
		return nil
	}
	m := new(GreetServerStreamRequest)
	if err := stream.RecvMsg(m); err != nil {
		return err
	}
	return srv.(GreetServiceServer).GreetServerStream(m, &greetServiceGreetServerStreamServer{stream})
}

type GreetService_GreetServerStreamServer interface {
	Send(*GreetServerStreamResponse) error
	grpc_go.ServerStream
}

type greetServiceGreetServerStreamServer struct {
	grpc_go.ServerStream
}

func (x *greetServiceGreetServerStreamServer) Send(m *GreetServerStreamResponse) error {
	return x.ServerStream.SendMsg(m)
}

// GreetService_ServiceDesc is the grpc_go.ServiceDesc for GreetService service.
// It's only intended for direct use with grpc_go.RegisterService,
// and not to be introspected or modified (even as a copy)
var GreetService_ServiceDesc = grpc_go.ServiceDesc{
	ServiceName: "greet.GreetService",
	HandlerType: (*GreetServiceServer)(nil),
	Methods: []grpc_go.MethodDesc{
		{
			MethodName: "Greet",
			Handler:    _GreetService_Greet_Handler,
		},
	},
	Streams: []grpc_go.StreamDesc{
		{
			StreamName:    "GreetStream",
			Handler:       _GreetService_GreetStream_Handler,
			ServerStreams: true,
			ClientStreams: true,
		},
		{
			StreamName:    "GreetClientStream",
			Handler:       _GreetService_GreetClientStream_Handler,
			ClientStreams: true,
		},
		{
			StreamName:    "GreetServerStream",
			Handler:       _GreetService_GreetServerStream_Handler,
			ServerStreams: true,
		},
	},
	Metadata: "internal/proto/greet.proto",
}
