//
// 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/EventService.go

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

import (
	reflect "reflect"

	gomock "github.com/golang/mock/gomock"
)

// MockEventServiceIface is a mock of EventServiceIface interface.
type MockEventServiceIface struct {
	ctrl     *gomock.Controller
	recorder *MockEventServiceIfaceMockRecorder
}

// MockEventServiceIfaceMockRecorder is the mock recorder for MockEventServiceIface.
type MockEventServiceIfaceMockRecorder struct {
	mock *MockEventServiceIface
}

// NewMockEventServiceIface creates a new mock instance.
func NewMockEventServiceIface(ctrl *gomock.Controller) *MockEventServiceIface {
	mock := &MockEventServiceIface{ctrl: ctrl}
	mock.recorder = &MockEventServiceIfaceMockRecorder{mock}
	return mock
}

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

// ArchiveEvents mocks base method.
func (m *MockEventServiceIface) ArchiveEvents(p *ArchiveEventsParams) (*ArchiveEventsResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "ArchiveEvents", p)
	ret0, _ := ret[0].(*ArchiveEventsResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

// ArchiveEvents indicates an expected call of ArchiveEvents.
func (mr *MockEventServiceIfaceMockRecorder) ArchiveEvents(p interface{}) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ArchiveEvents", reflect.TypeOf((*MockEventServiceIface)(nil).ArchiveEvents), p)
}

// DeleteEvents mocks base method.
func (m *MockEventServiceIface) DeleteEvents(p *DeleteEventsParams) (*DeleteEventsResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "DeleteEvents", p)
	ret0, _ := ret[0].(*DeleteEventsResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

// DeleteEvents indicates an expected call of DeleteEvents.
func (mr *MockEventServiceIfaceMockRecorder) DeleteEvents(p interface{}) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteEvents", reflect.TypeOf((*MockEventServiceIface)(nil).DeleteEvents), p)
}

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

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

// ListEventTypes mocks base method.
func (m *MockEventServiceIface) ListEventTypes(p *ListEventTypesParams) (*ListEventTypesResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "ListEventTypes", p)
	ret0, _ := ret[0].(*ListEventTypesResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

// ListEventTypes indicates an expected call of ListEventTypes.
func (mr *MockEventServiceIfaceMockRecorder) ListEventTypes(p interface{}) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListEventTypes", reflect.TypeOf((*MockEventServiceIface)(nil).ListEventTypes), p)
}

// ListEvents mocks base method.
func (m *MockEventServiceIface) ListEvents(p *ListEventsParams) (*ListEventsResponse, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "ListEvents", p)
	ret0, _ := ret[0].(*ListEventsResponse)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

// ListEvents indicates an expected call of ListEvents.
func (mr *MockEventServiceIfaceMockRecorder) ListEvents(p interface{}) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListEvents", reflect.TypeOf((*MockEventServiceIface)(nil).ListEvents), p)
}

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

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

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

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

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

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

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

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