//
// 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 MockGen. DO NOT EDIT.
// Source: ./cloudstack/NsxService.go
//
// Generated by this command:
//
//	mockgen -destination=./cloudstack/NsxService_mock.go -package=cloudstack -copyright_file=header.txt -source=./cloudstack/NsxService.go
//

// Package cloudstack is a generated GoMock package.
package cloudstack

import (
	reflect "reflect"

	gomock "go.uber.org/mock/gomock"
)

// MockNsxServiceIface is a mock of NsxServiceIface interface.
type MockNsxServiceIface struct {
	ctrl     *gomock.Controller
	recorder *MockNsxServiceIfaceMockRecorder
	isgomock struct{}
}

// MockNsxServiceIfaceMockRecorder is the mock recorder for MockNsxServiceIface.
type MockNsxServiceIfaceMockRecorder struct {
	mock *MockNsxServiceIface
}

// NewMockNsxServiceIface creates a new mock instance.
func NewMockNsxServiceIface(ctrl *gomock.Controller) *MockNsxServiceIface {
	mock := &MockNsxServiceIface{ctrl: ctrl}
	mock.recorder = &MockNsxServiceIfaceMockRecorder{mock}
	return mock
}

// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockNsxServiceIface) EXPECT() *MockNsxServiceIfaceMockRecorder {
	return m.recorder
}

// AddNsxController mocks base method.
func (m *MockNsxServiceIface) AddNsxController(p *AddNsxControllerParams) (*AddNsxControllerResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "AddNsxController", p)
	ret0, _ := ret[0].(*AddNsxControllerResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

// AddNsxController indicates an expected call of AddNsxController.
func (mr *MockNsxServiceIfaceMockRecorder) AddNsxController(p any) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddNsxController", reflect.TypeOf((*MockNsxServiceIface)(nil).AddNsxController), p)
}

// DeleteNsxController mocks base method.
func (m *MockNsxServiceIface) DeleteNsxController(p *DeleteNsxControllerParams) (*DeleteNsxControllerResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "DeleteNsxController", p)
	ret0, _ := ret[0].(*DeleteNsxControllerResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

// DeleteNsxController indicates an expected call of DeleteNsxController.
func (mr *MockNsxServiceIfaceMockRecorder) DeleteNsxController(p any) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteNsxController", reflect.TypeOf((*MockNsxServiceIface)(nil).DeleteNsxController), p)
}

// ListNsxControllers mocks base method.
func (m *MockNsxServiceIface) ListNsxControllers(p *ListNsxControllersParams) (*ListNsxControllersResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "ListNsxControllers", p)
	ret0, _ := ret[0].(*ListNsxControllersResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

// ListNsxControllers indicates an expected call of ListNsxControllers.
func (mr *MockNsxServiceIfaceMockRecorder) ListNsxControllers(p any) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListNsxControllers", reflect.TypeOf((*MockNsxServiceIface)(nil).ListNsxControllers), p)
}

// NewAddNsxControllerParams mocks base method.
func (m *MockNsxServiceIface) NewAddNsxControllerParams(edgecluster, name, nsxproviderhostname, password, tier0gateway, transportzone, username, zoneid string) *AddNsxControllerParams {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "NewAddNsxControllerParams", edgecluster, name, nsxproviderhostname, password, tier0gateway, transportzone, username, zoneid)
	ret0, _ := ret[0].(*AddNsxControllerParams)
	return ret0
}

// NewAddNsxControllerParams indicates an expected call of NewAddNsxControllerParams.
func (mr *MockNsxServiceIfaceMockRecorder) NewAddNsxControllerParams(edgecluster, name, nsxproviderhostname, password, tier0gateway, transportzone, username, zoneid any) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewAddNsxControllerParams", reflect.TypeOf((*MockNsxServiceIface)(nil).NewAddNsxControllerParams), edgecluster, name, nsxproviderhostname, password, tier0gateway, transportzone, username, zoneid)
}

// NewDeleteNsxControllerParams mocks base method.
func (m *MockNsxServiceIface) NewDeleteNsxControllerParams(nsxcontrollerid string) *DeleteNsxControllerParams {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "NewDeleteNsxControllerParams", nsxcontrollerid)
	ret0, _ := ret[0].(*DeleteNsxControllerParams)
	return ret0
}

// NewDeleteNsxControllerParams indicates an expected call of NewDeleteNsxControllerParams.
func (mr *MockNsxServiceIfaceMockRecorder) NewDeleteNsxControllerParams(nsxcontrollerid any) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewDeleteNsxControllerParams", reflect.TypeOf((*MockNsxServiceIface)(nil).NewDeleteNsxControllerParams), nsxcontrollerid)
}

// NewListNsxControllersParams mocks base method.
func (m *MockNsxServiceIface) NewListNsxControllersParams() *ListNsxControllersParams {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "NewListNsxControllersParams")
	ret0, _ := ret[0].(*ListNsxControllersParams)
	return ret0
}

// NewListNsxControllersParams indicates an expected call of NewListNsxControllersParams.
func (mr *MockNsxServiceIfaceMockRecorder) NewListNsxControllersParams() *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewListNsxControllersParams", reflect.TypeOf((*MockNsxServiceIface)(nil).NewListNsxControllersParams))
}
