// 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.

// Code generated by protoc-gen-go-grpc. DO NOT EDIT.

package v3

import (
	context "context"
	grpc "google.golang.org/grpc"
	codes "google.golang.org/grpc/codes"
	status "google.golang.org/grpc/status"
	v3 "skywalking/network/common/v3"
)

// 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.SupportPackageIsVersion7

// EventServiceClient is the client API for EventService 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 EventServiceClient interface {
	// When reporting an event, you typically call the collect function twice, one for starting of the event and the other one for ending of the event, with the same UUID.
	// There are also cases where you have both start time and end time already, for example, when exporting events from a 3rd-party system,
	// the start time and end time are already known so that you can call the collect function only once.
	Collect(ctx context.Context, opts ...grpc.CallOption) (EventService_CollectClient, error)
}

type eventServiceClient struct {
	cc grpc.ClientConnInterface
}

func NewEventServiceClient(cc grpc.ClientConnInterface) EventServiceClient {
	return &eventServiceClient{cc}
}

func (c *eventServiceClient) Collect(ctx context.Context, opts ...grpc.CallOption) (EventService_CollectClient, error) {
	stream, err := c.cc.NewStream(ctx, &_EventService_serviceDesc.Streams[0], "/skywalking.v3.EventService/collect", opts...)
	if err != nil {
		return nil, err
	}
	x := &eventServiceCollectClient{stream}
	return x, nil
}

type EventService_CollectClient interface {
	Send(*Event) error
	CloseAndRecv() (*v3.Commands, error)
	grpc.ClientStream
}

type eventServiceCollectClient struct {
	grpc.ClientStream
}

func (x *eventServiceCollectClient) Send(m *Event) error {
	return x.ClientStream.SendMsg(m)
}

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

// EventServiceServer is the server API for EventService service.
// All implementations must embed UnimplementedEventServiceServer
// for forward compatibility
type EventServiceServer interface {
	// When reporting an event, you typically call the collect function twice, one for starting of the event and the other one for ending of the event, with the same UUID.
	// There are also cases where you have both start time and end time already, for example, when exporting events from a 3rd-party system,
	// the start time and end time are already known so that you can call the collect function only once.
	Collect(EventService_CollectServer) error
	mustEmbedUnimplementedEventServiceServer()
}

// UnimplementedEventServiceServer must be embedded to have forward compatible implementations.
type UnimplementedEventServiceServer struct {
}

func (UnimplementedEventServiceServer) Collect(EventService_CollectServer) error {
	return status.Errorf(codes.Unimplemented, "method Collect not implemented")
}
func (UnimplementedEventServiceServer) mustEmbedUnimplementedEventServiceServer() {}

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

func RegisterEventServiceServer(s grpc.ServiceRegistrar, srv EventServiceServer) {
	s.RegisterService(&_EventService_serviceDesc, srv)
}

func _EventService_Collect_Handler(srv interface{}, stream grpc.ServerStream) error {
	return srv.(EventServiceServer).Collect(&eventServiceCollectServer{stream})
}

type EventService_CollectServer interface {
	SendAndClose(*v3.Commands) error
	Recv() (*Event, error)
	grpc.ServerStream
}

type eventServiceCollectServer struct {
	grpc.ServerStream
}

func (x *eventServiceCollectServer) SendAndClose(m *v3.Commands) error {
	return x.ServerStream.SendMsg(m)
}

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

var _EventService_serviceDesc = grpc.ServiceDesc{
	ServiceName: "skywalking.v3.EventService",
	HandlerType: (*EventServiceServer)(nil),
	Methods:     []grpc.MethodDesc{},
	Streams: []grpc.StreamDesc{
		{
			StreamName:    "collect",
			Handler:       _EventService_Collect_Handler,
			ClientStreams: true,
		},
	},
	Metadata: "event/Event.proto",
}
