/*
 * Copyright 2024 CloudWeGo 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.
 */

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

package mock

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 "google.golang.org/protobuf/proto"
)

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

var serviceMethods = map[string]kitex.MethodInfo{
	"UnaryTest": kitex.NewMethodInfo(
		unaryTestHandler,
		newUnaryTestArgs,
		newUnaryTestResult,
		false,
		kitex.WithStreamingMode(kitex.StreamingUnary),
	),
	"ClientStreamingTest": kitex.NewMethodInfo(
		clientStreamingTestHandler,
		newClientStreamingTestArgs,
		newClientStreamingTestResult,
		false,
		kitex.WithStreamingMode(kitex.StreamingClient),
	),
	"ServerStreamingTest": kitex.NewMethodInfo(
		serverStreamingTestHandler,
		newServerStreamingTestArgs,
		newServerStreamingTestResult,
		false,
		kitex.WithStreamingMode(kitex.StreamingServer),
	),
	"BidirectionalStreamingTest": kitex.NewMethodInfo(
		bidirectionalStreamingTestHandler,
		newBidirectionalStreamingTestArgs,
		newBidirectionalStreamingTestResult,
		false,
		kitex.WithStreamingMode(kitex.StreamingBidirectional),
	),
}

var (
	mockServiceInfo                = NewServiceInfo()
	mockServiceInfoForClient       = NewServiceInfoForClient()
	mockServiceInfoForStreamClient = NewServiceInfoForStreamClient()
)

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

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

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

// 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 := "Mock"
	handlerType := (*Mock)(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": "pbapi",
	}
	if hasStreaming {
		extra["streaming"] = hasStreaming
	}
	svcInfo := &kitex.ServiceInfo{
		ServiceName:     serviceName,
		HandlerType:     handlerType,
		Methods:         methods,
		PayloadCodec:    kitex.Protobuf,
		KiteXGenVersion: "v0.9.1",
		Extra:           extra,
	}
	return svcInfo
}

func unaryTestHandler(ctx context.Context, handler interface{}, arg, result interface{}) error {
	switch s := arg.(type) {
	case *streaming.Args:
		st := s.Stream
		req := new(MockReq)
		if err := st.RecvMsg(req); err != nil {
			return err
		}
		resp, err := handler.(Mock).UnaryTest(ctx, req)
		if err != nil {
			return err
		}
		return st.SendMsg(resp)
	case *UnaryTestArgs:
		success, err := handler.(Mock).UnaryTest(ctx, s.Req)
		if err != nil {
			return err
		}
		realResult := result.(*UnaryTestResult)
		realResult.Success = success
		return nil
	default:
		return errInvalidMessageType
	}
}
func newUnaryTestArgs() interface{} {
	return &UnaryTestArgs{}
}

func newUnaryTestResult() interface{} {
	return &UnaryTestResult{}
}

type UnaryTestArgs struct {
	Req *MockReq
}

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

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

var UnaryTestArgs_Req_DEFAULT *MockReq

func (p *UnaryTestArgs) GetReq() *MockReq {
	if !p.IsSetReq() {
		return UnaryTestArgs_Req_DEFAULT
	}
	return p.Req
}

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

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

type UnaryTestResult struct {
	Success *MockResp
}

var UnaryTestResult_Success_DEFAULT *MockResp

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

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

func (p *UnaryTestResult) GetSuccess() *MockResp {
	if !p.IsSetSuccess() {
		return UnaryTestResult_Success_DEFAULT
	}
	return p.Success
}

func (p *UnaryTestResult) SetSuccess(x interface{}) {
	p.Success = x.(*MockResp)
}

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

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

func clientStreamingTestHandler(ctx context.Context, handler interface{}, arg, result interface{}) error {
	streamingArgs, ok := arg.(*streaming.Args)
	if !ok {
		return errInvalidMessageType
	}
	st := streamingArgs.Stream
	stream := &mockClientStreamingTestServer{st}
	return handler.(Mock).ClientStreamingTest(stream)
}

type mockClientStreamingTestClient struct {
	streaming.Stream
}

func (x *mockClientStreamingTestClient) 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 *mockClientStreamingTestClient) Send(m *MockReq) error {
	return x.Stream.SendMsg(m)
}
func (x *mockClientStreamingTestClient) CloseAndRecv() (*MockResp, error) {
	if err := x.Stream.Close(); err != nil {
		return nil, err
	}
	m := new(MockResp)
	return m, x.Stream.RecvMsg(m)
}

type mockClientStreamingTestServer struct {
	streaming.Stream
}

func (x *mockClientStreamingTestServer) SendAndClose(m *MockResp) error {
	return x.Stream.SendMsg(m)
}

func (x *mockClientStreamingTestServer) Recv() (*MockReq, error) {
	m := new(MockReq)
	return m, x.Stream.RecvMsg(m)
}

func newClientStreamingTestArgs() interface{} {
	return &ClientStreamingTestArgs{}
}

func newClientStreamingTestResult() interface{} {
	return &ClientStreamingTestResult{}
}

type ClientStreamingTestArgs struct {
	Req *MockReq
}

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

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

var ClientStreamingTestArgs_Req_DEFAULT *MockReq

func (p *ClientStreamingTestArgs) GetReq() *MockReq {
	if !p.IsSetReq() {
		return ClientStreamingTestArgs_Req_DEFAULT
	}
	return p.Req
}

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

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

type ClientStreamingTestResult struct {
	Success *MockResp
}

var ClientStreamingTestResult_Success_DEFAULT *MockResp

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

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

func (p *ClientStreamingTestResult) GetSuccess() *MockResp {
	if !p.IsSetSuccess() {
		return ClientStreamingTestResult_Success_DEFAULT
	}
	return p.Success
}

func (p *ClientStreamingTestResult) SetSuccess(x interface{}) {
	p.Success = x.(*MockResp)
}

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

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

func serverStreamingTestHandler(ctx context.Context, handler interface{}, arg, result interface{}) error {
	streamingArgs, ok := arg.(*streaming.Args)
	if !ok {
		return errInvalidMessageType
	}
	st := streamingArgs.Stream
	stream := &mockServerStreamingTestServer{st}
	req := new(MockReq)
	if err := st.RecvMsg(req); err != nil {
		return err
	}
	return handler.(Mock).ServerStreamingTest(req, stream)
}

type mockServerStreamingTestClient struct {
	streaming.Stream
}

func (x *mockServerStreamingTestClient) 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 *mockServerStreamingTestClient) Recv() (*MockResp, error) {
	m := new(MockResp)
	return m, x.Stream.RecvMsg(m)
}

type mockServerStreamingTestServer struct {
	streaming.Stream
}

func (x *mockServerStreamingTestServer) Send(m *MockResp) error {
	return x.Stream.SendMsg(m)
}

func newServerStreamingTestArgs() interface{} {
	return &ServerStreamingTestArgs{}
}

func newServerStreamingTestResult() interface{} {
	return &ServerStreamingTestResult{}
}

type ServerStreamingTestArgs struct {
	Req *MockReq
}

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

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

var ServerStreamingTestArgs_Req_DEFAULT *MockReq

func (p *ServerStreamingTestArgs) GetReq() *MockReq {
	if !p.IsSetReq() {
		return ServerStreamingTestArgs_Req_DEFAULT
	}
	return p.Req
}

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

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

type ServerStreamingTestResult struct {
	Success *MockResp
}

var ServerStreamingTestResult_Success_DEFAULT *MockResp

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

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

func (p *ServerStreamingTestResult) GetSuccess() *MockResp {
	if !p.IsSetSuccess() {
		return ServerStreamingTestResult_Success_DEFAULT
	}
	return p.Success
}

func (p *ServerStreamingTestResult) SetSuccess(x interface{}) {
	p.Success = x.(*MockResp)
}

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

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

func bidirectionalStreamingTestHandler(ctx context.Context, handler interface{}, arg, result interface{}) error {
	streamingArgs, ok := arg.(*streaming.Args)
	if !ok {
		return errInvalidMessageType
	}
	st := streamingArgs.Stream
	stream := &mockBidirectionalStreamingTestServer{st}
	return handler.(Mock).BidirectionalStreamingTest(stream)
}

type mockBidirectionalStreamingTestClient struct {
	streaming.Stream
}

func (x *mockBidirectionalStreamingTestClient) 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 *mockBidirectionalStreamingTestClient) Send(m *MockReq) error {
	return x.Stream.SendMsg(m)
}
func (x *mockBidirectionalStreamingTestClient) Recv() (*MockResp, error) {
	m := new(MockResp)
	return m, x.Stream.RecvMsg(m)
}

type mockBidirectionalStreamingTestServer struct {
	streaming.Stream
}

func (x *mockBidirectionalStreamingTestServer) Send(m *MockResp) error {
	return x.Stream.SendMsg(m)
}

func (x *mockBidirectionalStreamingTestServer) Recv() (*MockReq, error) {
	m := new(MockReq)
	return m, x.Stream.RecvMsg(m)
}

func newBidirectionalStreamingTestArgs() interface{} {
	return &BidirectionalStreamingTestArgs{}
}

func newBidirectionalStreamingTestResult() interface{} {
	return &BidirectionalStreamingTestResult{}
}

type BidirectionalStreamingTestArgs struct {
	Req *MockReq
}

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

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

var BidirectionalStreamingTestArgs_Req_DEFAULT *MockReq

func (p *BidirectionalStreamingTestArgs) GetReq() *MockReq {
	if !p.IsSetReq() {
		return BidirectionalStreamingTestArgs_Req_DEFAULT
	}
	return p.Req
}

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

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

type BidirectionalStreamingTestResult struct {
	Success *MockResp
}

var BidirectionalStreamingTestResult_Success_DEFAULT *MockResp

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

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

func (p *BidirectionalStreamingTestResult) GetSuccess() *MockResp {
	if !p.IsSetSuccess() {
		return BidirectionalStreamingTestResult_Success_DEFAULT
	}
	return p.Success
}

func (p *BidirectionalStreamingTestResult) SetSuccess(x interface{}) {
	p.Success = x.(*MockResp)
}

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

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

type kClient struct {
	c client.Client
}

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

func (p *kClient) UnaryTest(ctx context.Context, Req *MockReq) (r *MockResp, err error) {
	var _args UnaryTestArgs
	_args.Req = Req
	var _result UnaryTestResult
	if err = p.c.Call(ctx, "UnaryTest", &_args, &_result); err != nil {
		return
	}
	return _result.GetSuccess(), nil
}

func (p *kClient) ClientStreamingTest(ctx context.Context) (Mock_ClientStreamingTestClient, 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, "ClientStreamingTest", nil, res)
	if err != nil {
		return nil, err
	}
	stream := &mockClientStreamingTestClient{res.Stream}
	return stream, nil
}

func (p *kClient) ServerStreamingTest(ctx context.Context, req *MockReq) (Mock_ServerStreamingTestClient, 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, "ServerStreamingTest", nil, res)
	if err != nil {
		return nil, err
	}
	stream := &mockServerStreamingTestClient{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) BidirectionalStreamingTest(ctx context.Context) (Mock_BidirectionalStreamingTestClient, 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, "BidirectionalStreamingTest", nil, res)
	if err != nil {
		return nil, err
	}
	stream := &mockBidirectionalStreamingTestClient{res.Stream}
	return stream, nil
}
