// Copyright 2010 Google Inc.
//
// Licensed 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.

package gomock

import (
	
	
	
	
)

// Call represents an expected call to a mock.
type Call struct {
	t TestHelper // for triggering test failures on invalid call setup

	receiver   interface{}  // the receiver of the method call
	method     string       // the name of the method
	methodType reflect.Type // the type of the method
	args       []Matcher    // the args
	origin     string       // file and line number of call setup

	preReqs []*Call // prerequisite calls

	// Expectations
	minCalls, maxCalls int

	numCalls int // actual number made

	// actions are called when this Call is called. Each action gets the args and
	// can set the return values by returning a non-nil slice. Actions run in the
	// order they are created.
	actions []func([]interface{}) []interface{}
}

// newCall creates a *Call. It requires the method type in order to support
// unexported methods.
func ( TestHelper,  interface{},  string,  reflect.Type,  ...interface{}) *Call {
	.Helper()

	// TODO: check arity, types.
	 := make([]Matcher, len())
	for ,  := range  {
		if ,  := .(Matcher);  {
			[] = 
		} else if  == nil {
			// Handle nil specially so that passing a nil interface value
			// will match the typed nils of concrete args.
			[] = Nil()
		} else {
			[] = Eq()
		}
	}

	// callerInfo's skip should be updated if the number of calls between the user's test
	// and this line changes, i.e. this code is wrapped in another anonymous function.
	// 0 is us, 1 is RecordCallWithMethodType(), 2 is the generated recorder, and 3 is the user's test.
	 := callerInfo(3)
	 := []func([]interface{}) []interface{}{func([]interface{}) []interface{} {
		// Synthesize the zero value for each of the return args' types.
		 := make([]interface{}, .NumOut())
		for  := 0;  < .NumOut(); ++ {
			[] = reflect.Zero(.Out()).Interface()
		}
		return 
	}}
	return &Call{t: , receiver: , method: , methodType: ,
		args: , origin: , minCalls: 1, maxCalls: 1, actions: }
}

// AnyTimes allows the expectation to be called 0 or more times
func ( *Call) () *Call {
	.minCalls, .maxCalls = 0, 1e8 // close enough to infinity
	return 
}

// MinTimes requires the call to occur at least n times. If AnyTimes or MaxTimes have not been called or if MaxTimes
// was previously called with 1, MinTimes also sets the maximum number of calls to infinity.
func ( *Call) ( int) *Call {
	.minCalls = 
	if .maxCalls == 1 {
		.maxCalls = 1e8
	}
	return 
}

// MaxTimes limits the number of calls to n times. If AnyTimes or MinTimes have not been called or if MinTimes was
// previously called with 1, MaxTimes also sets the minimum number of calls to 0.
func ( *Call) ( int) *Call {
	.maxCalls = 
	if .minCalls == 1 {
		.minCalls = 0
	}
	return 
}

// DoAndReturn declares the action to run when the call is matched.
// The return values from this function are returned by the mocked function.
// It takes an interface{} argument to support n-arity functions.
func ( *Call) ( interface{}) *Call {
	// TODO: Check arity and types here, rather than dying badly elsewhere.
	 := reflect.ValueOf()

	.addAction(func( []interface{}) []interface{} {
		.t.Helper()
		 := make([]reflect.Value, len())
		 := .Type()
		if .methodType.NumIn() != .NumIn() {
			.t.Fatalf("wrong number of arguments in DoAndReturn func for %T.%v: got %d, want %d [%s]",
				.receiver, .method, .NumIn(), .methodType.NumIn(), .origin)
			return nil
		}
		for  := 0;  < len(); ++ {
			if [] != nil {
				[] = reflect.ValueOf([])
			} else {
				// Use the zero value for the arg.
				[] = reflect.Zero(.In())
			}
		}
		 := .Call()
		 := make([]interface{}, len())
		for ,  := range  {
			[] = .Interface()
		}
		return 
	})
	return 
}

// Do declares the action to run when the call is matched. The function's
// return values are ignored to retain backward compatibility. To use the
// return values call DoAndReturn.
// It takes an interface{} argument to support n-arity functions.
func ( *Call) ( interface{}) *Call {
	// TODO: Check arity and types here, rather than dying badly elsewhere.
	 := reflect.ValueOf()

	.addAction(func( []interface{}) []interface{} {
		.t.Helper()
		if .methodType.NumIn() != .Type().NumIn() {
			.t.Fatalf("wrong number of arguments in Do func for %T.%v: got %d, want %d [%s]",
				.receiver, .method, .Type().NumIn(), .methodType.NumIn(), .origin)
			return nil
		}
		 := make([]reflect.Value, len())
		 := .Type()
		for  := 0;  < len(); ++ {
			if [] != nil {
				[] = reflect.ValueOf([])
			} else {
				// Use the zero value for the arg.
				[] = reflect.Zero(.In())
			}
		}
		.Call()
		return nil
	})
	return 
}

// Return declares the values to be returned by the mocked function call.
func ( *Call) ( ...interface{}) *Call {
	.t.Helper()

	 := .methodType
	if len() != .NumOut() {
		.t.Fatalf("wrong number of arguments to Return for %T.%v: got %d, want %d [%s]",
			.receiver, .method, len(), .NumOut(), .origin)
	}
	for ,  := range  {
		if ,  := reflect.TypeOf(), .Out();  ==  {
			// Identical types; nothing to do.
		} else if  == nil {
			// Nil needs special handling.
			switch .Kind() {
			case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
				// ok
			default:
				.t.Fatalf("argument %d to Return for %T.%v is nil, but %v is not nillable [%s]",
					, .receiver, .method, , .origin)
			}
		} else if .AssignableTo() {
			// Assignable type relation. Make the assignment now so that the generated code
			// can return the values with a type assertion.
			 := reflect.New().Elem()
			.Set(reflect.ValueOf())
			[] = .Interface()
		} else {
			.t.Fatalf("wrong type of argument %d to Return for %T.%v: %v is not assignable to %v [%s]",
				, .receiver, .method, , , .origin)
		}
	}

	.addAction(func([]interface{}) []interface{} {
		return 
	})

	return 
}

// Times declares the exact number of times a function call is expected to be executed.
func ( *Call) ( int) *Call {
	.minCalls, .maxCalls = , 
	return 
}

// SetArg declares an action that will set the nth argument's value,
// indirected through a pointer. Or, in the case of a slice, SetArg
// will copy value's elements into the nth argument.
func ( *Call) ( int,  interface{}) *Call {
	.t.Helper()

	 := .methodType
	// TODO: This will break on variadic methods.
	// We will need to check those at invocation time.
	if  < 0 ||  >= .NumIn() {
		.t.Fatalf("SetArg(%d, ...) called for a method with %d args [%s]",
			, .NumIn(), .origin)
	}
	// Permit setting argument through an interface.
	// In the interface case, we don't (nay, can't) check the type here.
	 := .In()
	switch .Kind() {
	case reflect.Ptr:
		 := .Elem()
		if  := reflect.TypeOf(); !.AssignableTo() {
			.t.Fatalf("SetArg(%d, ...) argument is a %v, not assignable to %v [%s]",
				, , , .origin)
		}
	case reflect.Interface:
		// nothing to do
	case reflect.Slice:
		// nothing to do
	default:
		.t.Fatalf("SetArg(%d, ...) referring to argument of non-pointer non-interface non-slice type %v [%s]",
			, , .origin)
	}

	.addAction(func( []interface{}) []interface{} {
		 := reflect.ValueOf()
		switch reflect.TypeOf([]).Kind() {
		case reflect.Slice:
			setSlice([], )
		default:
			reflect.ValueOf([]).Elem().Set()
		}
		return nil
	})
	return 
}

// isPreReq returns true if other is a direct or indirect prerequisite to c.
func ( *Call) ( *Call) bool {
	for ,  := range .preReqs {
		if  ==  || .() {
			return true
		}
	}
	return false
}

// After declares that the call may only match after preReq has been exhausted.
func ( *Call) ( *Call) *Call {
	.t.Helper()

	if  ==  {
		.t.Fatalf("A call isn't allowed to be its own prerequisite")
	}
	if .isPreReq() {
		.t.Fatalf("Loop in call order: %v is a prerequisite to %v (possibly indirectly).", , )
	}

	.preReqs = append(.preReqs, )
	return 
}

// Returns true if the minimum number of calls have been made.
func ( *Call) () bool {
	return .numCalls >= .minCalls
}

// Returns true if the maximum number of calls have been made.
func ( *Call) () bool {
	return .numCalls >= .maxCalls
}

func ( *Call) () string {
	 := make([]string, len(.args))
	for ,  := range .args {
		[] = .String()
	}
	 := strings.Join(, ", ")
	return fmt.Sprintf("%T.%v(%s) %s", .receiver, .method, , .origin)
}

// Tests if the given call matches the expected call.
// If yes, returns nil. If no, returns error with message explaining why it does not match.
func ( *Call) ( []interface{}) error {
	if !.methodType.IsVariadic() {
		if len() != len(.args) {
			return fmt.Errorf("expected call at %s has the wrong number of arguments. Got: %d, want: %d",
				.origin, len(), len(.args))
		}

		for ,  := range .args {
			if !.Matches([]) {
				return fmt.Errorf(
					"expected call at %s doesn't match the argument at index %d.\nGot: %v\nWant: %v",
					.origin, , formatGottenArg(, []), ,
				)
			}
		}
	} else {
		if len(.args) < .methodType.NumIn()-1 {
			return fmt.Errorf("expected call at %s has the wrong number of matchers. Got: %d, want: %d",
				.origin, len(.args), .methodType.NumIn()-1)
		}
		if len(.args) != .methodType.NumIn() && len() != len(.args) {
			return fmt.Errorf("expected call at %s has the wrong number of arguments. Got: %d, want: %d",
				.origin, len(), len(.args))
		}
		if len() < len(.args)-1 {
			return fmt.Errorf("expected call at %s has the wrong number of arguments. Got: %d, want: greater than or equal to %d",
				.origin, len(), len(.args)-1)
		}

		for ,  := range .args {
			if  < .methodType.NumIn()-1 {
				// Non-variadic args
				if !.Matches([]) {
					return fmt.Errorf("expected call at %s doesn't match the argument at index %s.\nGot: %v\nWant: %v",
						.origin, strconv.Itoa(), formatGottenArg(, []), )
				}
				continue
			}
			// The last arg has a possibility of a variadic argument, so let it branch

			// sample: Foo(a int, b int, c ...int)
			if  < len(.args) &&  < len() {
				if .Matches([]) {
					// Got Foo(a, b, c) want Foo(matcherA, matcherB, gomock.Any())
					// Got Foo(a, b, c) want Foo(matcherA, matcherB, someSliceMatcher)
					// Got Foo(a, b, c) want Foo(matcherA, matcherB, matcherC)
					// Got Foo(a, b) want Foo(matcherA, matcherB)
					// Got Foo(a, b, c, d) want Foo(matcherA, matcherB, matcherC, matcherD)
					continue
				}
			}

			// The number of actual args don't match the number of matchers,
			// or the last matcher is a slice and the last arg is not.
			// If this function still matches it is because the last matcher
			// matches all the remaining arguments or the lack of any.
			// Convert the remaining arguments, if any, into a slice of the
			// expected type.
			 := .methodType.In(.methodType.NumIn() - 1)
			 := reflect.MakeSlice(, 0, len()-)
			for ,  := range [:] {
				 = reflect.Append(, reflect.ValueOf())
			}
			if .Matches(.Interface()) {
				// Got Foo(a, b, c, d, e) want Foo(matcherA, matcherB, gomock.Any())
				// Got Foo(a, b, c, d, e) want Foo(matcherA, matcherB, someSliceMatcher)
				// Got Foo(a, b) want Foo(matcherA, matcherB, gomock.Any())
				// Got Foo(a, b) want Foo(matcherA, matcherB, someEmptySliceMatcher)
				break
			}
			// Wrong number of matchers or not match. Fail.
			// Got Foo(a, b) want Foo(matcherA, matcherB, matcherC, matcherD)
			// Got Foo(a, b, c) want Foo(matcherA, matcherB, matcherC, matcherD)
			// Got Foo(a, b, c, d) want Foo(matcherA, matcherB, matcherC, matcherD, matcherE)
			// Got Foo(a, b, c, d, e) want Foo(matcherA, matcherB, matcherC, matcherD)
			// Got Foo(a, b, c) want Foo(matcherA, matcherB)

			return fmt.Errorf("expected call at %s doesn't match the argument at index %s.\nGot: %v\nWant: %v",
				.origin, strconv.Itoa(), formatGottenArg(, [:]), .args[])
		}
	}

	// Check that all prerequisite calls have been satisfied.
	for ,  := range .preReqs {
		if !.satisfied() {
			return fmt.Errorf("expected call at %s doesn't have a prerequisite call satisfied:\n%v\nshould be called before:\n%v",
				.origin, , )
		}
	}

	// Check that the call is not exhausted.
	if .exhausted() {
		return fmt.Errorf("expected call at %s has already been called the max number of times", .origin)
	}

	return nil
}

// dropPrereqs tells the expected Call to not re-check prerequisite calls any
// longer, and to return its current set.
func ( *Call) () ( []*Call) {
	 = .preReqs
	.preReqs = nil
	return
}

func ( *Call) () []func([]interface{}) []interface{} {
	.numCalls++
	return .actions
}

// InOrder declares that the given calls should occur in order.
func ( ...*Call) {
	for  := 1;  < len(); ++ {
		[].After([-1])
	}
}

func ( interface{},  reflect.Value) {
	 := reflect.ValueOf()
	for  := 0;  < .Len(); ++ {
		.Index().Set(.Index())
	}
}

func ( *Call) ( func([]interface{}) []interface{}) {
	.actions = append(.actions, )
}

func ( Matcher,  interface{}) string {
	 := fmt.Sprintf("%v (%T)", , )
	if ,  := .(GotFormatter);  {
		 = .Got()
	}
	return 
}