/*
 * 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
 *
 *   https://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 mockery v2.28.2. DO NOT EDIT.

package _default

import (
	context "context"

	model "github.com/apache/plc4x/plc4go/pkg/api/model"
	mock "github.com/stretchr/testify/mock"
)

// MockDefaultBrowser is an autogenerated mock type for the DefaultBrowser type
type MockDefaultBrowser struct {
	mock.Mock
}

type MockDefaultBrowser_Expecter struct {
	mock *mock.Mock
}

func (_m *MockDefaultBrowser) EXPECT() *MockDefaultBrowser_Expecter {
	return &MockDefaultBrowser_Expecter{mock: &_m.Mock}
}

// Browse provides a mock function with given fields: ctx, browseRequest
func (_m *MockDefaultBrowser) Browse(ctx context.Context, browseRequest model.PlcBrowseRequest) <-chan model.PlcBrowseRequestResult {
	ret := _m.Called(ctx, browseRequest)

	var r0 <-chan model.PlcBrowseRequestResult
	if rf, ok := ret.Get(0).(func(context.Context, model.PlcBrowseRequest) <-chan model.PlcBrowseRequestResult); ok {
		r0 = rf(ctx, browseRequest)
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).(<-chan model.PlcBrowseRequestResult)
		}
	}

	return r0
}

// MockDefaultBrowser_Browse_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Browse'
type MockDefaultBrowser_Browse_Call struct {
	*mock.Call
}

// Browse is a helper method to define mock.On call
//   - ctx context.Context
//   - browseRequest model.PlcBrowseRequest
func (_e *MockDefaultBrowser_Expecter) Browse(ctx interface{}, browseRequest interface{}) *MockDefaultBrowser_Browse_Call {
	return &MockDefaultBrowser_Browse_Call{Call: _e.mock.On("Browse", ctx, browseRequest)}
}

func (_c *MockDefaultBrowser_Browse_Call) Run(run func(ctx context.Context, browseRequest model.PlcBrowseRequest)) *MockDefaultBrowser_Browse_Call {
	_c.Call.Run(func(args mock.Arguments) {
		run(args[0].(context.Context), args[1].(model.PlcBrowseRequest))
	})
	return _c
}

func (_c *MockDefaultBrowser_Browse_Call) Return(_a0 <-chan model.PlcBrowseRequestResult) *MockDefaultBrowser_Browse_Call {
	_c.Call.Return(_a0)
	return _c
}

func (_c *MockDefaultBrowser_Browse_Call) RunAndReturn(run func(context.Context, model.PlcBrowseRequest) <-chan model.PlcBrowseRequestResult) *MockDefaultBrowser_Browse_Call {
	_c.Call.Return(run)
	return _c
}

// BrowseWithInterceptor provides a mock function with given fields: ctx, browseRequest, interceptor
func (_m *MockDefaultBrowser) BrowseWithInterceptor(ctx context.Context, browseRequest model.PlcBrowseRequest, interceptor func(model.PlcBrowseItem) bool) <-chan model.PlcBrowseRequestResult {
	ret := _m.Called(ctx, browseRequest, interceptor)

	var r0 <-chan model.PlcBrowseRequestResult
	if rf, ok := ret.Get(0).(func(context.Context, model.PlcBrowseRequest, func(model.PlcBrowseItem) bool) <-chan model.PlcBrowseRequestResult); ok {
		r0 = rf(ctx, browseRequest, interceptor)
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).(<-chan model.PlcBrowseRequestResult)
		}
	}

	return r0
}

// MockDefaultBrowser_BrowseWithInterceptor_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BrowseWithInterceptor'
type MockDefaultBrowser_BrowseWithInterceptor_Call struct {
	*mock.Call
}

// BrowseWithInterceptor is a helper method to define mock.On call
//   - ctx context.Context
//   - browseRequest model.PlcBrowseRequest
//   - interceptor func(model.PlcBrowseItem) bool
func (_e *MockDefaultBrowser_Expecter) BrowseWithInterceptor(ctx interface{}, browseRequest interface{}, interceptor interface{}) *MockDefaultBrowser_BrowseWithInterceptor_Call {
	return &MockDefaultBrowser_BrowseWithInterceptor_Call{Call: _e.mock.On("BrowseWithInterceptor", ctx, browseRequest, interceptor)}
}

func (_c *MockDefaultBrowser_BrowseWithInterceptor_Call) Run(run func(ctx context.Context, browseRequest model.PlcBrowseRequest, interceptor func(model.PlcBrowseItem) bool)) *MockDefaultBrowser_BrowseWithInterceptor_Call {
	_c.Call.Run(func(args mock.Arguments) {
		run(args[0].(context.Context), args[1].(model.PlcBrowseRequest), args[2].(func(model.PlcBrowseItem) bool))
	})
	return _c
}

func (_c *MockDefaultBrowser_BrowseWithInterceptor_Call) Return(_a0 <-chan model.PlcBrowseRequestResult) *MockDefaultBrowser_BrowseWithInterceptor_Call {
	_c.Call.Return(_a0)
	return _c
}

func (_c *MockDefaultBrowser_BrowseWithInterceptor_Call) RunAndReturn(run func(context.Context, model.PlcBrowseRequest, func(model.PlcBrowseItem) bool) <-chan model.PlcBrowseRequestResult) *MockDefaultBrowser_BrowseWithInterceptor_Call {
	_c.Call.Return(run)
	return _c
}

type mockConstructorTestingTNewMockDefaultBrowser interface {
	mock.TestingT
	Cleanup(func())
}

// NewMockDefaultBrowser creates a new instance of MockDefaultBrowser. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
func NewMockDefaultBrowser(t mockConstructorTestingTNewMockDefaultBrowser) *MockDefaultBrowser {
	mock := &MockDefaultBrowser{}
	mock.Mock.Test(t)

	t.Cleanup(func() { mock.AssertExpectations(t) })

	return mock
}
