/*
 * 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-triple. DO NOT EDIT.
//
// Source: protocol\triple\health\triple_health\health.proto
package triple_health

import (
	"context"
	"net/http"
)

import (
	"dubbo.apache.org/dubbo-go/v3/client"
	"dubbo.apache.org/dubbo-go/v3/common/constant"
	"dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol"
	"dubbo.apache.org/dubbo-go/v3/server"
)

// This is a compile-time assertion to ensure that this generated file and the Triple package
// are compatible. If you get a compiler error that this constant is not defined, this code was
// generated with a version of Triple newer than the one compiled into your binary. You can fix the
// problem by either regenerating this code with an older version of Triple or updating the Triple
// version compiled into your binary.
const _ = triple_protocol.IsAtLeastVersion0_1_0

const (
	// HealthName is the fully-qualified name of the Health service.
	HealthName = "grpc.health.v1.Health"
)

// These constants are the fully-qualified names of the RPCs defined in this package. They're
// exposed at runtime as procedure and as the final two segments of the HTTP route.
//
// Note that these are different from the fully-qualified method names used by
// google.golang.org/protobuf/reflect/protoreflect. To convert from these constants to
// reflection-formatted method names, remove the leading slash and convert the remaining slash to a
// period.
const (
	// HealthCheckProcedure is the fully-qualified name of the Health's Check RPC.
	HealthCheckProcedure = "/grpc.health.v1.Health/Check"
	// HealthWatchProcedure is the fully-qualified name of the Health's Watch RPC.
	HealthWatchProcedure = "/grpc.health.v1.Health/Watch"
)

var (
	_ Health = (*HealthImpl)(nil)

	_ Health_WatchClient = (*HealthWatchClient)(nil)

	_ Health_WatchServer = (*HealthWatchServer)(nil)
)

// Health is a client for the grpc.health.v1.Health service.
type Health interface {
	Check(ctx context.Context, req *HealthCheckRequest, opts ...client.CallOption) (*HealthCheckResponse, error)
	Watch(ctx context.Context, req *HealthCheckRequest, opts ...client.CallOption) (Health_WatchClient, error)
}

// NewHealth constructs a client for the grpc.health.v1.Health service.
func NewHealth(cli *client.Client) (Health, error) {
	if err := cli.Init(&Health_ClientInfo); err != nil {
		return nil, err
	}
	return &HealthImpl{
		cli: cli,
	}, nil
}

// HealthImpl implements Health.
type HealthImpl struct {
	cli *client.Client
}

func (c *HealthImpl) Check(ctx context.Context, req *HealthCheckRequest, opts ...client.CallOption) (*HealthCheckResponse, error) {
	resp := new(HealthCheckResponse)
	if err := c.cli.CallUnary(ctx, req, resp, "grpc.health.v1.Health", "Check", opts...); err != nil {
		return nil, err
	}
	return resp, nil
}

func (c *HealthImpl) Watch(ctx context.Context, req *HealthCheckRequest, opts ...client.CallOption) (Health_WatchClient, error) {
	stream, err := c.cli.CallServerStream(ctx, req, "grpc.health.v1.Health", "Watch", opts...)
	if err != nil {
		return nil, err
	}
	rawStream := stream.(*triple_protocol.ServerStreamForClient)
	return &HealthWatchClient{rawStream}, nil
}

type Health_WatchClient interface {
	Recv() bool
	ResponseHeader() http.Header
	ResponseTrailer() http.Header
	Msg() *HealthCheckResponse
	Err() error
	Conn() (triple_protocol.StreamingClientConn, error)
	Close() error
}

type HealthWatchClient struct {
	*triple_protocol.ServerStreamForClient
}

func (cli *HealthWatchClient) Recv() bool {
	msg := new(HealthCheckResponse)
	return cli.ServerStreamForClient.Receive(msg)
}

func (cli *HealthWatchClient) Msg() *HealthCheckResponse {
	msg := cli.ServerStreamForClient.Msg()
	if msg == nil {
		return new(HealthCheckResponse)
	}
	return msg.(*HealthCheckResponse)
}

func (cli *HealthWatchClient) Conn() (triple_protocol.StreamingClientConn, error) {
	return cli.ServerStreamForClient.Conn()
}

var Health_ClientInfo = client.ClientInfo{
	InterfaceName: "grpc.health.v1.Health",
	MethodNames:   []string{"Check", "Watch"},
	ClientInjectFunc: func(dubboCliRaw interface{}, cli *client.Client) {
		dubboCli := dubboCliRaw.(HealthImpl)
		dubboCli.cli = cli
	},
}

// HealthHandler is an implementation of the grpc.health.v1.Health service.
type HealthHandler interface {
	Check(context.Context, *HealthCheckRequest) (*HealthCheckResponse, error)
	Watch(context.Context, *HealthCheckRequest, Health_WatchServer) error
}

func RegisterHealthHandler(srv *server.Server, hdlr HealthHandler, opts ...server.ServiceOption) error {
	return srv.Register(hdlr, &Health_ServiceInfo, opts...)
}

type Health_WatchServer interface {
	Send(*HealthCheckResponse) error
	ResponseHeader() http.Header
	ResponseTrailer() http.Header
	Conn() triple_protocol.StreamingHandlerConn
}

type HealthWatchServer struct {
	*triple_protocol.ServerStream
}

func (g *HealthWatchServer) Send(msg *HealthCheckResponse) error {
	return g.ServerStream.Send(msg)
}

var Health_ServiceInfo = server.ServiceInfo{
	InterfaceName: "grpc.health.v1.Health",
	ServiceType:   (*HealthHandler)(nil),
	Methods: []server.MethodInfo{
		{
			Name: "Check",
			Type: constant.CallUnary,
			ReqInitFunc: func() interface{} {
				return new(HealthCheckRequest)
			},
			MethodFunc: func(ctx context.Context, args []interface{}, handler interface{}) (interface{}, error) {
				req := args[0].(*HealthCheckRequest)
				res, err := handler.(HealthHandler).Check(ctx, req)
				if err != nil {
					return nil, err
				}
				return triple_protocol.NewResponse(res), nil
			},
		},
		{
			Name: "Watch",
			Type: constant.CallServerStream,
			ReqInitFunc: func() interface{} {
				return new(HealthCheckRequest)
			},
			StreamInitFunc: func(baseStream interface{}) interface{} {
				return &HealthWatchServer{baseStream.(*triple_protocol.ServerStream)}
			},
			MethodFunc: func(ctx context.Context, args []interface{}, handler interface{}) (interface{}, error) {
				req := args[0].(*HealthCheckRequest)
				stream := args[1].(Health_WatchServer)
				if err := handler.(HealthHandler).Watch(ctx, req, stream); err != nil {
					return nil, err
				}
				return nil, nil
			},
		},
	},
}
