/*
 * 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.
 */

package thrift

import "context"

// ProcessorMiddleware is a function that can be passed to WrapProcessor to wrap the
// TProcessorFunctions for that TProcessor.
//
// Middlewares are passed in the name of the function as set in the processor
// map of the TProcessor.
type ProcessorMiddleware func(name string, next TProcessorFunction) TProcessorFunction

// WrapProcessor takes an existing TProcessor and wraps each of its inner
// TProcessorFunctions with the middlewares passed in and returns it.
//
// Middlewares will be called in the order that they are defined:
//
//		1. Middlewares[0]
//		2. Middlewares[1]
//		...
//		N. Middlewares[n]
func WrapProcessor(processor TProcessor, middlewares ...ProcessorMiddleware) TProcessor {
	for name, processorFunc := range processor.ProcessorMap() {
		wrapped := processorFunc
		// Add middlewares in reverse so the first in the list is the outermost.
		for i := len(middlewares) - 1; i >= 0; i-- {
			wrapped = middlewares[i](name, wrapped)
		}
		processor.AddToProcessorMap(name, wrapped)
	}
	return processor
}

// WrappedTProcessorFunction is a convenience struct that implements the
// TProcessorFunction interface that can be used when implementing custom
// Middleware.
type WrappedTProcessorFunction struct {
	// Wrapped is called by WrappedTProcessorFunction.Process and should be a
	// "wrapped" call to a base TProcessorFunc.Process call.
	Wrapped func(ctx context.Context, seqId int32, in, out TProtocol) (bool, TException)
}

// Process implements the TProcessorFunction interface using p.Wrapped.
func (p WrappedTProcessorFunction) Process(ctx context.Context, seqID int32, in, out TProtocol) (bool, TException) {
	return p.Wrapped(ctx, seqID, in, out)
}

// verify that WrappedTProcessorFunction implements TProcessorFunction
var (
	_ TProcessorFunction = WrappedTProcessorFunction{}
	_ TProcessorFunction = (*WrappedTProcessorFunction)(nil)
)

// ClientMiddleware can be passed to WrapClient in order to wrap TClient calls
// with custom middleware.
type ClientMiddleware func(TClient) TClient

// WrappedTClient is a convenience struct that implements the TClient interface
// using inner Wrapped function.
//
// This is provided to aid in developing ClientMiddleware.
type WrappedTClient struct {
	Wrapped func(ctx context.Context, method string, args, result TStruct) error
}

// Call implements the TClient interface by calling and returning c.Wrapped.
func (c WrappedTClient) Call(ctx context.Context, method string, args, result TStruct) error {
	return c.Wrapped(ctx, method, args, result)
}

// verify that WrappedTClient implements TClient
var (
	_ TClient = WrappedTClient{}
	_ TClient = (*WrappedTClient)(nil)
)

// WrapClient wraps the given TClient in the given middlewares.
//
// Middlewares will be called in the order that they are defined:
//
//		1. Middlewares[0]
//		2. Middlewares[1]
//		...
//		N. Middlewares[n]
func WrapClient(client TClient, middlewares ...ClientMiddleware) TClient {
	// Add middlewares in reverse so the first in the list is the outermost.
	for i := len(middlewares) - 1; i >= 0; i-- {
		client = middlewares[i](client)
	}
	return client
}
