// Code generated by Kitex v0.13.1. DO NOT EDIT.

package streamingservice

import (
	"context"
	"errors"
	"fmt"
	client "github.com/cloudwego/kitex/client"
	kitex "github.com/cloudwego/kitex/pkg/serviceinfo"
	streaming "github.com/cloudwego/kitex/pkg/streaming"
	proto "github.com/cloudwego/prutal"
	pb "pb_generic_streaming_demo/kitex_gen/pb"
)

var errInvalidMessageType = errors.New("invalid message type for service method handler")

var serviceMethods = map[string]kitex.MethodInfo{
	"StreamRequestEcho": kitex.NewMethodInfo(
		streamRequestEchoHandler,
		newStreamRequestEchoArgs,
		newStreamRequestEchoResult,
		false,
		kitex.WithStreamingMode(kitex.StreamingClient),
	),
	"StreamResponseEcho": kitex.NewMethodInfo(
		streamResponseEchoHandler,
		newStreamResponseEchoArgs,
		newStreamResponseEchoResult,
		false,
		kitex.WithStreamingMode(kitex.StreamingServer),
	),
	"BidirectionalEcho": kitex.NewMethodInfo(
		bidirectionalEchoHandler,
		newBidirectionalEchoArgs,
		newBidirectionalEchoResult,
		false,
		kitex.WithStreamingMode(kitex.StreamingBidirectional),
	),
	"UnaryEcho": kitex.NewMethodInfo(
		unaryEchoHandler,
		newUnaryEchoArgs,
		newUnaryEchoResult,
		false,
		kitex.WithStreamingMode(kitex.StreamingUnary),
	),
}

var (
	streamingServiceServiceInfo                = NewServiceInfo()
	streamingServiceServiceInfoForClient       = NewServiceInfoForClient()
	streamingServiceServiceInfoForStreamClient = NewServiceInfoForStreamClient()
)

// for server
func serviceInfo() *kitex.ServiceInfo {
	return streamingServiceServiceInfo
}

// for stream client
func serviceInfoForStreamClient() *kitex.ServiceInfo {
	return streamingServiceServiceInfoForStreamClient
}

// for client
func serviceInfoForClient() *kitex.ServiceInfo {
	return streamingServiceServiceInfoForClient
}

// NewServiceInfo creates a new ServiceInfo containing all methods
func NewServiceInfo() *kitex.ServiceInfo {
	return newServiceInfo(true, true, true)
}

// NewServiceInfo creates a new ServiceInfo containing non-streaming methods
func NewServiceInfoForClient() *kitex.ServiceInfo {
	return newServiceInfo(false, false, true)
}
func NewServiceInfoForStreamClient() *kitex.ServiceInfo {
	return newServiceInfo(true, true, false)
}

func newServiceInfo(hasStreaming bool, keepStreamingMethods bool, keepNonStreamingMethods bool) *kitex.ServiceInfo {
	serviceName := "StreamingService"
	handlerType := (*pb.StreamingService)(nil)
	methods := map[string]kitex.MethodInfo{}
	for name, m := range serviceMethods {
		if m.IsStreaming() && !keepStreamingMethods {
			continue
		}
		if !m.IsStreaming() && !keepNonStreamingMethods {
			continue
		}
		methods[name] = m
	}
	extra := map[string]interface{}{
		"PackageName": "pb",
	}
	if hasStreaming {
		extra["streaming"] = hasStreaming
	}
	svcInfo := &kitex.ServiceInfo{
		ServiceName:     serviceName,
		HandlerType:     handlerType,
		Methods:         methods,
		PayloadCodec:    kitex.Protobuf,
		KiteXGenVersion: "v0.13.1",
		Extra:           extra,
	}
	return svcInfo
}

func streamRequestEchoHandler(ctx context.Context, handler interface{}, arg, result interface{}) error {
	streamingArgs, ok := arg.(*streaming.Args)
	if !ok {
		return errInvalidMessageType
	}
	st := streamingArgs.Stream
	stream := &streamingServiceStreamRequestEchoServer{st}
	return handler.(pb.StreamingService).StreamRequestEcho(stream)
}

type streamingServiceStreamRequestEchoClient struct {
	streaming.Stream
}

func (x *streamingServiceStreamRequestEchoClient) DoFinish(err error) {
	if finisher, ok := x.Stream.(streaming.WithDoFinish); ok {
		finisher.DoFinish(err)
	} else {
		panic(fmt.Sprintf("streaming.WithDoFinish is not implemented by %T", x.Stream))
	}
}
func (x *streamingServiceStreamRequestEchoClient) Send(m *pb.Request) error {
	return x.Stream.SendMsg(m)
}
func (x *streamingServiceStreamRequestEchoClient) CloseAndRecv() (*pb.Response, error) {
	if err := x.Stream.Close(); err != nil {
		return nil, err
	}
	m := new(pb.Response)
	return m, x.Stream.RecvMsg(m)
}

type streamingServiceStreamRequestEchoServer struct {
	streaming.Stream
}

func (x *streamingServiceStreamRequestEchoServer) SendAndClose(m *pb.Response) error {
	return x.Stream.SendMsg(m)
}

func (x *streamingServiceStreamRequestEchoServer) Recv() (*pb.Request, error) {
	m := new(pb.Request)
	return m, x.Stream.RecvMsg(m)
}

func newStreamRequestEchoArgs() interface{} {
	return &StreamRequestEchoArgs{}
}

func newStreamRequestEchoResult() interface{} {
	return &StreamRequestEchoResult{}
}

type StreamRequestEchoArgs struct {
	Req *pb.Request
}

func (p *StreamRequestEchoArgs) Marshal(out []byte) ([]byte, error) {
	if !p.IsSetReq() {
		return out, nil
	}
	return proto.Marshal(p.Req)
}

func (p *StreamRequestEchoArgs) Unmarshal(in []byte) error {
	msg := new(pb.Request)
	if err := proto.Unmarshal(in, msg); err != nil {
		return err
	}
	p.Req = msg
	return nil
}

var StreamRequestEchoArgs_Req_DEFAULT *pb.Request

func (p *StreamRequestEchoArgs) GetReq() *pb.Request {
	if !p.IsSetReq() {
		return StreamRequestEchoArgs_Req_DEFAULT
	}
	return p.Req
}

func (p *StreamRequestEchoArgs) IsSetReq() bool {
	return p.Req != nil
}

func (p *StreamRequestEchoArgs) GetFirstArgument() interface{} {
	return p.Req
}

type StreamRequestEchoResult struct {
	Success *pb.Response
}

var StreamRequestEchoResult_Success_DEFAULT *pb.Response

func (p *StreamRequestEchoResult) Marshal(out []byte) ([]byte, error) {
	if !p.IsSetSuccess() {
		return out, nil
	}
	return proto.Marshal(p.Success)
}

func (p *StreamRequestEchoResult) Unmarshal(in []byte) error {
	msg := new(pb.Response)
	if err := proto.Unmarshal(in, msg); err != nil {
		return err
	}
	p.Success = msg
	return nil
}

func (p *StreamRequestEchoResult) GetSuccess() *pb.Response {
	if !p.IsSetSuccess() {
		return StreamRequestEchoResult_Success_DEFAULT
	}
	return p.Success
}

func (p *StreamRequestEchoResult) SetSuccess(x interface{}) {
	p.Success = x.(*pb.Response)
}

func (p *StreamRequestEchoResult) IsSetSuccess() bool {
	return p.Success != nil
}

func (p *StreamRequestEchoResult) GetResult() interface{} {
	return p.Success
}

func streamResponseEchoHandler(ctx context.Context, handler interface{}, arg, result interface{}) error {
	streamingArgs, ok := arg.(*streaming.Args)
	if !ok {
		return errInvalidMessageType
	}
	st := streamingArgs.Stream
	stream := &streamingServiceStreamResponseEchoServer{st}
	req := new(pb.Request)
	if err := st.RecvMsg(req); err != nil {
		return err
	}
	return handler.(pb.StreamingService).StreamResponseEcho(req, stream)
}

type streamingServiceStreamResponseEchoClient struct {
	streaming.Stream
}

func (x *streamingServiceStreamResponseEchoClient) DoFinish(err error) {
	if finisher, ok := x.Stream.(streaming.WithDoFinish); ok {
		finisher.DoFinish(err)
	} else {
		panic(fmt.Sprintf("streaming.WithDoFinish is not implemented by %T", x.Stream))
	}
}
func (x *streamingServiceStreamResponseEchoClient) Recv() (*pb.Response, error) {
	m := new(pb.Response)
	return m, x.Stream.RecvMsg(m)
}

type streamingServiceStreamResponseEchoServer struct {
	streaming.Stream
}

func (x *streamingServiceStreamResponseEchoServer) Send(m *pb.Response) error {
	return x.Stream.SendMsg(m)
}

func newStreamResponseEchoArgs() interface{} {
	return &StreamResponseEchoArgs{}
}

func newStreamResponseEchoResult() interface{} {
	return &StreamResponseEchoResult{}
}

type StreamResponseEchoArgs struct {
	Req *pb.Request
}

func (p *StreamResponseEchoArgs) Marshal(out []byte) ([]byte, error) {
	if !p.IsSetReq() {
		return out, nil
	}
	return proto.Marshal(p.Req)
}

func (p *StreamResponseEchoArgs) Unmarshal(in []byte) error {
	msg := new(pb.Request)
	if err := proto.Unmarshal(in, msg); err != nil {
		return err
	}
	p.Req = msg
	return nil
}

var StreamResponseEchoArgs_Req_DEFAULT *pb.Request

func (p *StreamResponseEchoArgs) GetReq() *pb.Request {
	if !p.IsSetReq() {
		return StreamResponseEchoArgs_Req_DEFAULT
	}
	return p.Req
}

func (p *StreamResponseEchoArgs) IsSetReq() bool {
	return p.Req != nil
}

func (p *StreamResponseEchoArgs) GetFirstArgument() interface{} {
	return p.Req
}

type StreamResponseEchoResult struct {
	Success *pb.Response
}

var StreamResponseEchoResult_Success_DEFAULT *pb.Response

func (p *StreamResponseEchoResult) Marshal(out []byte) ([]byte, error) {
	if !p.IsSetSuccess() {
		return out, nil
	}
	return proto.Marshal(p.Success)
}

func (p *StreamResponseEchoResult) Unmarshal(in []byte) error {
	msg := new(pb.Response)
	if err := proto.Unmarshal(in, msg); err != nil {
		return err
	}
	p.Success = msg
	return nil
}

func (p *StreamResponseEchoResult) GetSuccess() *pb.Response {
	if !p.IsSetSuccess() {
		return StreamResponseEchoResult_Success_DEFAULT
	}
	return p.Success
}

func (p *StreamResponseEchoResult) SetSuccess(x interface{}) {
	p.Success = x.(*pb.Response)
}

func (p *StreamResponseEchoResult) IsSetSuccess() bool {
	return p.Success != nil
}

func (p *StreamResponseEchoResult) GetResult() interface{} {
	return p.Success
}

func bidirectionalEchoHandler(ctx context.Context, handler interface{}, arg, result interface{}) error {
	streamingArgs, ok := arg.(*streaming.Args)
	if !ok {
		return errInvalidMessageType
	}
	st := streamingArgs.Stream
	stream := &streamingServiceBidirectionalEchoServer{st}
	return handler.(pb.StreamingService).BidirectionalEcho(stream)
}

type streamingServiceBidirectionalEchoClient struct {
	streaming.Stream
}

func (x *streamingServiceBidirectionalEchoClient) DoFinish(err error) {
	if finisher, ok := x.Stream.(streaming.WithDoFinish); ok {
		finisher.DoFinish(err)
	} else {
		panic(fmt.Sprintf("streaming.WithDoFinish is not implemented by %T", x.Stream))
	}
}
func (x *streamingServiceBidirectionalEchoClient) Send(m *pb.Request) error {
	return x.Stream.SendMsg(m)
}
func (x *streamingServiceBidirectionalEchoClient) Recv() (*pb.Response, error) {
	m := new(pb.Response)
	return m, x.Stream.RecvMsg(m)
}

type streamingServiceBidirectionalEchoServer struct {
	streaming.Stream
}

func (x *streamingServiceBidirectionalEchoServer) Send(m *pb.Response) error {
	return x.Stream.SendMsg(m)
}

func (x *streamingServiceBidirectionalEchoServer) Recv() (*pb.Request, error) {
	m := new(pb.Request)
	return m, x.Stream.RecvMsg(m)
}

func newBidirectionalEchoArgs() interface{} {
	return &BidirectionalEchoArgs{}
}

func newBidirectionalEchoResult() interface{} {
	return &BidirectionalEchoResult{}
}

type BidirectionalEchoArgs struct {
	Req *pb.Request
}

func (p *BidirectionalEchoArgs) Marshal(out []byte) ([]byte, error) {
	if !p.IsSetReq() {
		return out, nil
	}
	return proto.Marshal(p.Req)
}

func (p *BidirectionalEchoArgs) Unmarshal(in []byte) error {
	msg := new(pb.Request)
	if err := proto.Unmarshal(in, msg); err != nil {
		return err
	}
	p.Req = msg
	return nil
}

var BidirectionalEchoArgs_Req_DEFAULT *pb.Request

func (p *BidirectionalEchoArgs) GetReq() *pb.Request {
	if !p.IsSetReq() {
		return BidirectionalEchoArgs_Req_DEFAULT
	}
	return p.Req
}

func (p *BidirectionalEchoArgs) IsSetReq() bool {
	return p.Req != nil
}

func (p *BidirectionalEchoArgs) GetFirstArgument() interface{} {
	return p.Req
}

type BidirectionalEchoResult struct {
	Success *pb.Response
}

var BidirectionalEchoResult_Success_DEFAULT *pb.Response

func (p *BidirectionalEchoResult) Marshal(out []byte) ([]byte, error) {
	if !p.IsSetSuccess() {
		return out, nil
	}
	return proto.Marshal(p.Success)
}

func (p *BidirectionalEchoResult) Unmarshal(in []byte) error {
	msg := new(pb.Response)
	if err := proto.Unmarshal(in, msg); err != nil {
		return err
	}
	p.Success = msg
	return nil
}

func (p *BidirectionalEchoResult) GetSuccess() *pb.Response {
	if !p.IsSetSuccess() {
		return BidirectionalEchoResult_Success_DEFAULT
	}
	return p.Success
}

func (p *BidirectionalEchoResult) SetSuccess(x interface{}) {
	p.Success = x.(*pb.Response)
}

func (p *BidirectionalEchoResult) IsSetSuccess() bool {
	return p.Success != nil
}

func (p *BidirectionalEchoResult) GetResult() interface{} {
	return p.Success
}

func unaryEchoHandler(ctx context.Context, handler interface{}, arg, result interface{}) error {
	switch s := arg.(type) {
	case *streaming.Args:
		st := s.Stream
		req := new(pb.Request)
		if err := st.RecvMsg(req); err != nil {
			return err
		}
		resp, err := handler.(pb.StreamingService).UnaryEcho(ctx, req)
		if err != nil {
			return err
		}
		return st.SendMsg(resp)
	case *UnaryEchoArgs:
		success, err := handler.(pb.StreamingService).UnaryEcho(ctx, s.Req)
		if err != nil {
			return err
		}
		realResult := result.(*UnaryEchoResult)
		realResult.Success = success
		return nil
	default:
		return errInvalidMessageType
	}
}
func newUnaryEchoArgs() interface{} {
	return &UnaryEchoArgs{}
}

func newUnaryEchoResult() interface{} {
	return &UnaryEchoResult{}
}

type UnaryEchoArgs struct {
	Req *pb.Request
}

func (p *UnaryEchoArgs) Marshal(out []byte) ([]byte, error) {
	if !p.IsSetReq() {
		return out, nil
	}
	return proto.Marshal(p.Req)
}

func (p *UnaryEchoArgs) Unmarshal(in []byte) error {
	msg := new(pb.Request)
	if err := proto.Unmarshal(in, msg); err != nil {
		return err
	}
	p.Req = msg
	return nil
}

var UnaryEchoArgs_Req_DEFAULT *pb.Request

func (p *UnaryEchoArgs) GetReq() *pb.Request {
	if !p.IsSetReq() {
		return UnaryEchoArgs_Req_DEFAULT
	}
	return p.Req
}

func (p *UnaryEchoArgs) IsSetReq() bool {
	return p.Req != nil
}

func (p *UnaryEchoArgs) GetFirstArgument() interface{} {
	return p.Req
}

type UnaryEchoResult struct {
	Success *pb.Response
}

var UnaryEchoResult_Success_DEFAULT *pb.Response

func (p *UnaryEchoResult) Marshal(out []byte) ([]byte, error) {
	if !p.IsSetSuccess() {
		return out, nil
	}
	return proto.Marshal(p.Success)
}

func (p *UnaryEchoResult) Unmarshal(in []byte) error {
	msg := new(pb.Response)
	if err := proto.Unmarshal(in, msg); err != nil {
		return err
	}
	p.Success = msg
	return nil
}

func (p *UnaryEchoResult) GetSuccess() *pb.Response {
	if !p.IsSetSuccess() {
		return UnaryEchoResult_Success_DEFAULT
	}
	return p.Success
}

func (p *UnaryEchoResult) SetSuccess(x interface{}) {
	p.Success = x.(*pb.Response)
}

func (p *UnaryEchoResult) IsSetSuccess() bool {
	return p.Success != nil
}

func (p *UnaryEchoResult) GetResult() interface{} {
	return p.Success
}

type kClient struct {
	c client.Client
}

func newServiceClient(c client.Client) *kClient {
	return &kClient{
		c: c,
	}
}

func (p *kClient) StreamRequestEcho(ctx context.Context) (StreamingService_StreamRequestEchoClient, error) {
	streamClient, ok := p.c.(client.Streaming)
	if !ok {
		return nil, fmt.Errorf("client not support streaming")
	}
	res := new(streaming.Result)
	err := streamClient.Stream(ctx, "StreamRequestEcho", nil, res)
	if err != nil {
		return nil, err
	}
	stream := &streamingServiceStreamRequestEchoClient{res.Stream}
	return stream, nil
}

func (p *kClient) StreamResponseEcho(ctx context.Context, req *pb.Request) (StreamingService_StreamResponseEchoClient, error) {
	streamClient, ok := p.c.(client.Streaming)
	if !ok {
		return nil, fmt.Errorf("client not support streaming")
	}
	res := new(streaming.Result)
	err := streamClient.Stream(ctx, "StreamResponseEcho", nil, res)
	if err != nil {
		return nil, err
	}
	stream := &streamingServiceStreamResponseEchoClient{res.Stream}

	if err := stream.Stream.SendMsg(req); err != nil {
		return nil, err
	}
	if err := stream.Stream.Close(); err != nil {
		return nil, err
	}
	return stream, nil
}

func (p *kClient) BidirectionalEcho(ctx context.Context) (StreamingService_BidirectionalEchoClient, error) {
	streamClient, ok := p.c.(client.Streaming)
	if !ok {
		return nil, fmt.Errorf("client not support streaming")
	}
	res := new(streaming.Result)
	err := streamClient.Stream(ctx, "BidirectionalEcho", nil, res)
	if err != nil {
		return nil, err
	}
	stream := &streamingServiceBidirectionalEchoClient{res.Stream}
	return stream, nil
}

func (p *kClient) UnaryEcho(ctx context.Context, Req *pb.Request) (r *pb.Response, err error) {
	var _args UnaryEchoArgs
	_args.Req = Req
	var _result UnaryEchoResult
	if err = p.c.Call(ctx, "UnaryEcho", &_args, &_result); err != nil {
		return
	}
	return _result.GetSuccess(), nil
}
