//
// 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/ServiceOfferingService.go
//
// Generated by this command:
//
//	mockgen -destination=./cloudstack/ServiceOfferingService_mock.go -package=cloudstack -copyright_file=header.txt -source=./cloudstack/ServiceOfferingService.go
//

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

import (
	reflect "reflect"

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

// MockServiceOfferingServiceIface is a mock of ServiceOfferingServiceIface interface.
type MockServiceOfferingServiceIface struct {
	ctrl     *gomock.Controller
	recorder *MockServiceOfferingServiceIfaceMockRecorder
	isgomock struct{}
}

// MockServiceOfferingServiceIfaceMockRecorder is the mock recorder for MockServiceOfferingServiceIface.
type MockServiceOfferingServiceIfaceMockRecorder struct {
	mock *MockServiceOfferingServiceIface
}

// NewMockServiceOfferingServiceIface creates a new mock instance.
func NewMockServiceOfferingServiceIface(ctrl *gomock.Controller) *MockServiceOfferingServiceIface {
	mock := &MockServiceOfferingServiceIface{ctrl: ctrl}
	mock.recorder = &MockServiceOfferingServiceIfaceMockRecorder{mock}
	return mock
}

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

// CreateServiceOffering mocks base method.
func (m *MockServiceOfferingServiceIface) CreateServiceOffering(p *CreateServiceOfferingParams) (*CreateServiceOfferingResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "CreateServiceOffering", p)
	ret0, _ := ret[0].(*CreateServiceOfferingResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

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

// DeleteServiceOffering mocks base method.
func (m *MockServiceOfferingServiceIface) DeleteServiceOffering(p *DeleteServiceOfferingParams) (*DeleteServiceOfferingResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "DeleteServiceOffering", p)
	ret0, _ := ret[0].(*DeleteServiceOfferingResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

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

// GetServiceOfferingByID mocks base method.
func (m *MockServiceOfferingServiceIface) GetServiceOfferingByID(id string, opts ...OptionFunc) (*ServiceOffering, int, error) {
	m.ctrl.T.Helper()
	varargs := []any{id}
	for _, a := range opts {
		varargs = append(varargs, a)
	}
	ret := m.ctrl.Call(m, "GetServiceOfferingByID", varargs...)
	ret0, _ := ret[0].(*ServiceOffering)
	ret1, _ := ret[1].(int)
	ret2, _ := ret[2].(error)
	return ret0, ret1, ret2
}

// GetServiceOfferingByID indicates an expected call of GetServiceOfferingByID.
func (mr *MockServiceOfferingServiceIfaceMockRecorder) GetServiceOfferingByID(id any, opts ...any) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	varargs := append([]any{id}, opts...)
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetServiceOfferingByID", reflect.TypeOf((*MockServiceOfferingServiceIface)(nil).GetServiceOfferingByID), varargs...)
}

// GetServiceOfferingByName mocks base method.
func (m *MockServiceOfferingServiceIface) GetServiceOfferingByName(name string, opts ...OptionFunc) (*ServiceOffering, int, error) {
	m.ctrl.T.Helper()
	varargs := []any{name}
	for _, a := range opts {
		varargs = append(varargs, a)
	}
	ret := m.ctrl.Call(m, "GetServiceOfferingByName", varargs...)
	ret0, _ := ret[0].(*ServiceOffering)
	ret1, _ := ret[1].(int)
	ret2, _ := ret[2].(error)
	return ret0, ret1, ret2
}

// GetServiceOfferingByName indicates an expected call of GetServiceOfferingByName.
func (mr *MockServiceOfferingServiceIfaceMockRecorder) GetServiceOfferingByName(name any, opts ...any) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	varargs := append([]any{name}, opts...)
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetServiceOfferingByName", reflect.TypeOf((*MockServiceOfferingServiceIface)(nil).GetServiceOfferingByName), varargs...)
}

// GetServiceOfferingID mocks base method.
func (m *MockServiceOfferingServiceIface) GetServiceOfferingID(name string, opts ...OptionFunc) (string, int, error) {
	m.ctrl.T.Helper()
	varargs := []any{name}
	for _, a := range opts {
		varargs = append(varargs, a)
	}
	ret := m.ctrl.Call(m, "GetServiceOfferingID", varargs...)
	ret0, _ := ret[0].(string)
	ret1, _ := ret[1].(int)
	ret2, _ := ret[2].(error)
	return ret0, ret1, ret2
}

// GetServiceOfferingID indicates an expected call of GetServiceOfferingID.
func (mr *MockServiceOfferingServiceIfaceMockRecorder) GetServiceOfferingID(name any, opts ...any) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	varargs := append([]any{name}, opts...)
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetServiceOfferingID", reflect.TypeOf((*MockServiceOfferingServiceIface)(nil).GetServiceOfferingID), varargs...)
}

// ListServiceOfferings mocks base method.
func (m *MockServiceOfferingServiceIface) ListServiceOfferings(p *ListServiceOfferingsParams) (*ListServiceOfferingsResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "ListServiceOfferings", p)
	ret0, _ := ret[0].(*ListServiceOfferingsResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

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

// NewCreateServiceOfferingParams mocks base method.
func (m *MockServiceOfferingServiceIface) NewCreateServiceOfferingParams(displaytext, name string) *CreateServiceOfferingParams {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "NewCreateServiceOfferingParams", displaytext, name)
	ret0, _ := ret[0].(*CreateServiceOfferingParams)
	return ret0
}

// NewCreateServiceOfferingParams indicates an expected call of NewCreateServiceOfferingParams.
func (mr *MockServiceOfferingServiceIfaceMockRecorder) NewCreateServiceOfferingParams(displaytext, name any) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewCreateServiceOfferingParams", reflect.TypeOf((*MockServiceOfferingServiceIface)(nil).NewCreateServiceOfferingParams), displaytext, name)
}

// NewDeleteServiceOfferingParams mocks base method.
func (m *MockServiceOfferingServiceIface) NewDeleteServiceOfferingParams(id string) *DeleteServiceOfferingParams {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "NewDeleteServiceOfferingParams", id)
	ret0, _ := ret[0].(*DeleteServiceOfferingParams)
	return ret0
}

// NewDeleteServiceOfferingParams indicates an expected call of NewDeleteServiceOfferingParams.
func (mr *MockServiceOfferingServiceIfaceMockRecorder) NewDeleteServiceOfferingParams(id any) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewDeleteServiceOfferingParams", reflect.TypeOf((*MockServiceOfferingServiceIface)(nil).NewDeleteServiceOfferingParams), id)
}

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

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

// NewUpdateServiceOfferingParams mocks base method.
func (m *MockServiceOfferingServiceIface) NewUpdateServiceOfferingParams(id string) *UpdateServiceOfferingParams {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "NewUpdateServiceOfferingParams", id)
	ret0, _ := ret[0].(*UpdateServiceOfferingParams)
	return ret0
}

// NewUpdateServiceOfferingParams indicates an expected call of NewUpdateServiceOfferingParams.
func (mr *MockServiceOfferingServiceIfaceMockRecorder) NewUpdateServiceOfferingParams(id any) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewUpdateServiceOfferingParams", reflect.TypeOf((*MockServiceOfferingServiceIface)(nil).NewUpdateServiceOfferingParams), id)
}

// UpdateServiceOffering mocks base method.
func (m *MockServiceOfferingServiceIface) UpdateServiceOffering(p *UpdateServiceOfferingParams) (*UpdateServiceOfferingResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "UpdateServiceOffering", p)
	ret0, _ := ret[0].(*UpdateServiceOfferingResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

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