//go:build go1.18
// +build go1.18

// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
// Code generated by Microsoft (R) AutoRest Code Generator. DO NOT EDIT.
// Changes may cause incorrect behavior and will be lost if the code is regenerated.

package fake

import (
	"errors"
	"fmt"
	"net/http"
	"strings"
	"sync"

	"github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
)

// ServerFactory is a fake server for instances of the armbilling.ClientFactory type.
type ServerFactory struct {
	AccountsServer             AccountsServer
	AddressServer              AddressServer
	AgreementsServer           AgreementsServer
	AssociatedTenantsServer    AssociatedTenantsServer
	AvailableBalancesServer    AvailableBalancesServer
	CustomersServer            CustomersServer
	DepartmentsServer          DepartmentsServer
	EnrollmentAccountsServer   EnrollmentAccountsServer
	InvoiceSectionsServer      InvoiceSectionsServer
	InvoicesServer             InvoicesServer
	OperationsServer           OperationsServer
	PartnerTransfersServer     PartnerTransfersServer
	PaymentMethodsServer       PaymentMethodsServer
	PermissionsServer          PermissionsServer
	PoliciesServer             PoliciesServer
	ProductsServer             ProductsServer
	ProfilesServer             ProfilesServer
	PropertyServer             PropertyServer
	RecipientTransfersServer   RecipientTransfersServer
	RequestsServer             RequestsServer
	ReservationOrdersServer    ReservationOrdersServer
	ReservationsServer         ReservationsServer
	RoleAssignmentsServer      RoleAssignmentsServer
	RoleDefinitionServer       RoleDefinitionServer
	SavingsPlanOrdersServer    SavingsPlanOrdersServer
	SavingsPlansServer         SavingsPlansServer
	SubscriptionsAliasesServer SubscriptionsAliasesServer
	SubscriptionsServer        SubscriptionsServer
	TransactionsServer         TransactionsServer
	TransfersServer            TransfersServer
}

// NewServerFactoryTransport creates a new instance of ServerFactoryTransport with the provided implementation.
// The returned ServerFactoryTransport instance is connected to an instance of armbilling.ClientFactory via the
// azcore.ClientOptions.Transporter field in the client's constructor parameters.
func NewServerFactoryTransport(srv *ServerFactory) *ServerFactoryTransport {
	return &ServerFactoryTransport{
		srv: srv,
	}
}

// ServerFactoryTransport connects instances of armbilling.ClientFactory to instances of ServerFactory.
// Don't use this type directly, use NewServerFactoryTransport instead.
type ServerFactoryTransport struct {
	srv                          *ServerFactory
	trMu                         sync.Mutex
	trAccountsServer             *AccountsServerTransport
	trAddressServer              *AddressServerTransport
	trAgreementsServer           *AgreementsServerTransport
	trAssociatedTenantsServer    *AssociatedTenantsServerTransport
	trAvailableBalancesServer    *AvailableBalancesServerTransport
	trCustomersServer            *CustomersServerTransport
	trDepartmentsServer          *DepartmentsServerTransport
	trEnrollmentAccountsServer   *EnrollmentAccountsServerTransport
	trInvoiceSectionsServer      *InvoiceSectionsServerTransport
	trInvoicesServer             *InvoicesServerTransport
	trOperationsServer           *OperationsServerTransport
	trPartnerTransfersServer     *PartnerTransfersServerTransport
	trPaymentMethodsServer       *PaymentMethodsServerTransport
	trPermissionsServer          *PermissionsServerTransport
	trPoliciesServer             *PoliciesServerTransport
	trProductsServer             *ProductsServerTransport
	trProfilesServer             *ProfilesServerTransport
	trPropertyServer             *PropertyServerTransport
	trRecipientTransfersServer   *RecipientTransfersServerTransport
	trRequestsServer             *RequestsServerTransport
	trReservationOrdersServer    *ReservationOrdersServerTransport
	trReservationsServer         *ReservationsServerTransport
	trRoleAssignmentsServer      *RoleAssignmentsServerTransport
	trRoleDefinitionServer       *RoleDefinitionServerTransport
	trSavingsPlanOrdersServer    *SavingsPlanOrdersServerTransport
	trSavingsPlansServer         *SavingsPlansServerTransport
	trSubscriptionsAliasesServer *SubscriptionsAliasesServerTransport
	trSubscriptionsServer        *SubscriptionsServerTransport
	trTransactionsServer         *TransactionsServerTransport
	trTransfersServer            *TransfersServerTransport
}

// Do implements the policy.Transporter interface for ServerFactoryTransport.
func (s *ServerFactoryTransport) Do(req *http.Request) (*http.Response, error) {
	rawMethod := req.Context().Value(runtime.CtxAPINameKey{})
	method, ok := rawMethod.(string)
	if !ok {
		return nil, nonRetriableError{errors.New("unable to dispatch request, missing value for CtxAPINameKey")}
	}

	client := method[:strings.Index(method, ".")]
	var resp *http.Response
	var err error

	switch client {
	case "AccountsClient":
		initServer(s, &s.trAccountsServer, func() *AccountsServerTransport { return NewAccountsServerTransport(&s.srv.AccountsServer) })
		resp, err = s.trAccountsServer.Do(req)
	case "AddressClient":
		initServer(s, &s.trAddressServer, func() *AddressServerTransport { return NewAddressServerTransport(&s.srv.AddressServer) })
		resp, err = s.trAddressServer.Do(req)
	case "AgreementsClient":
		initServer(s, &s.trAgreementsServer, func() *AgreementsServerTransport { return NewAgreementsServerTransport(&s.srv.AgreementsServer) })
		resp, err = s.trAgreementsServer.Do(req)
	case "AssociatedTenantsClient":
		initServer(s, &s.trAssociatedTenantsServer, func() *AssociatedTenantsServerTransport {
			return NewAssociatedTenantsServerTransport(&s.srv.AssociatedTenantsServer)
		})
		resp, err = s.trAssociatedTenantsServer.Do(req)
	case "AvailableBalancesClient":
		initServer(s, &s.trAvailableBalancesServer, func() *AvailableBalancesServerTransport {
			return NewAvailableBalancesServerTransport(&s.srv.AvailableBalancesServer)
		})
		resp, err = s.trAvailableBalancesServer.Do(req)
	case "CustomersClient":
		initServer(s, &s.trCustomersServer, func() *CustomersServerTransport { return NewCustomersServerTransport(&s.srv.CustomersServer) })
		resp, err = s.trCustomersServer.Do(req)
	case "DepartmentsClient":
		initServer(s, &s.trDepartmentsServer, func() *DepartmentsServerTransport { return NewDepartmentsServerTransport(&s.srv.DepartmentsServer) })
		resp, err = s.trDepartmentsServer.Do(req)
	case "EnrollmentAccountsClient":
		initServer(s, &s.trEnrollmentAccountsServer, func() *EnrollmentAccountsServerTransport {
			return NewEnrollmentAccountsServerTransport(&s.srv.EnrollmentAccountsServer)
		})
		resp, err = s.trEnrollmentAccountsServer.Do(req)
	case "InvoiceSectionsClient":
		initServer(s, &s.trInvoiceSectionsServer, func() *InvoiceSectionsServerTransport {
			return NewInvoiceSectionsServerTransport(&s.srv.InvoiceSectionsServer)
		})
		resp, err = s.trInvoiceSectionsServer.Do(req)
	case "InvoicesClient":
		initServer(s, &s.trInvoicesServer, func() *InvoicesServerTransport { return NewInvoicesServerTransport(&s.srv.InvoicesServer) })
		resp, err = s.trInvoicesServer.Do(req)
	case "OperationsClient":
		initServer(s, &s.trOperationsServer, func() *OperationsServerTransport { return NewOperationsServerTransport(&s.srv.OperationsServer) })
		resp, err = s.trOperationsServer.Do(req)
	case "PartnerTransfersClient":
		initServer(s, &s.trPartnerTransfersServer, func() *PartnerTransfersServerTransport {
			return NewPartnerTransfersServerTransport(&s.srv.PartnerTransfersServer)
		})
		resp, err = s.trPartnerTransfersServer.Do(req)
	case "PaymentMethodsClient":
		initServer(s, &s.trPaymentMethodsServer, func() *PaymentMethodsServerTransport {
			return NewPaymentMethodsServerTransport(&s.srv.PaymentMethodsServer)
		})
		resp, err = s.trPaymentMethodsServer.Do(req)
	case "PermissionsClient":
		initServer(s, &s.trPermissionsServer, func() *PermissionsServerTransport { return NewPermissionsServerTransport(&s.srv.PermissionsServer) })
		resp, err = s.trPermissionsServer.Do(req)
	case "PoliciesClient":
		initServer(s, &s.trPoliciesServer, func() *PoliciesServerTransport { return NewPoliciesServerTransport(&s.srv.PoliciesServer) })
		resp, err = s.trPoliciesServer.Do(req)
	case "ProductsClient":
		initServer(s, &s.trProductsServer, func() *ProductsServerTransport { return NewProductsServerTransport(&s.srv.ProductsServer) })
		resp, err = s.trProductsServer.Do(req)
	case "ProfilesClient":
		initServer(s, &s.trProfilesServer, func() *ProfilesServerTransport { return NewProfilesServerTransport(&s.srv.ProfilesServer) })
		resp, err = s.trProfilesServer.Do(req)
	case "PropertyClient":
		initServer(s, &s.trPropertyServer, func() *PropertyServerTransport { return NewPropertyServerTransport(&s.srv.PropertyServer) })
		resp, err = s.trPropertyServer.Do(req)
	case "RecipientTransfersClient":
		initServer(s, &s.trRecipientTransfersServer, func() *RecipientTransfersServerTransport {
			return NewRecipientTransfersServerTransport(&s.srv.RecipientTransfersServer)
		})
		resp, err = s.trRecipientTransfersServer.Do(req)
	case "RequestsClient":
		initServer(s, &s.trRequestsServer, func() *RequestsServerTransport { return NewRequestsServerTransport(&s.srv.RequestsServer) })
		resp, err = s.trRequestsServer.Do(req)
	case "ReservationOrdersClient":
		initServer(s, &s.trReservationOrdersServer, func() *ReservationOrdersServerTransport {
			return NewReservationOrdersServerTransport(&s.srv.ReservationOrdersServer)
		})
		resp, err = s.trReservationOrdersServer.Do(req)
	case "ReservationsClient":
		initServer(s, &s.trReservationsServer, func() *ReservationsServerTransport { return NewReservationsServerTransport(&s.srv.ReservationsServer) })
		resp, err = s.trReservationsServer.Do(req)
	case "RoleAssignmentsClient":
		initServer(s, &s.trRoleAssignmentsServer, func() *RoleAssignmentsServerTransport {
			return NewRoleAssignmentsServerTransport(&s.srv.RoleAssignmentsServer)
		})
		resp, err = s.trRoleAssignmentsServer.Do(req)
	case "RoleDefinitionClient":
		initServer(s, &s.trRoleDefinitionServer, func() *RoleDefinitionServerTransport {
			return NewRoleDefinitionServerTransport(&s.srv.RoleDefinitionServer)
		})
		resp, err = s.trRoleDefinitionServer.Do(req)
	case "SavingsPlanOrdersClient":
		initServer(s, &s.trSavingsPlanOrdersServer, func() *SavingsPlanOrdersServerTransport {
			return NewSavingsPlanOrdersServerTransport(&s.srv.SavingsPlanOrdersServer)
		})
		resp, err = s.trSavingsPlanOrdersServer.Do(req)
	case "SavingsPlansClient":
		initServer(s, &s.trSavingsPlansServer, func() *SavingsPlansServerTransport { return NewSavingsPlansServerTransport(&s.srv.SavingsPlansServer) })
		resp, err = s.trSavingsPlansServer.Do(req)
	case "SubscriptionsAliasesClient":
		initServer(s, &s.trSubscriptionsAliasesServer, func() *SubscriptionsAliasesServerTransport {
			return NewSubscriptionsAliasesServerTransport(&s.srv.SubscriptionsAliasesServer)
		})
		resp, err = s.trSubscriptionsAliasesServer.Do(req)
	case "SubscriptionsClient":
		initServer(s, &s.trSubscriptionsServer, func() *SubscriptionsServerTransport {
			return NewSubscriptionsServerTransport(&s.srv.SubscriptionsServer)
		})
		resp, err = s.trSubscriptionsServer.Do(req)
	case "TransactionsClient":
		initServer(s, &s.trTransactionsServer, func() *TransactionsServerTransport { return NewTransactionsServerTransport(&s.srv.TransactionsServer) })
		resp, err = s.trTransactionsServer.Do(req)
	case "TransfersClient":
		initServer(s, &s.trTransfersServer, func() *TransfersServerTransport { return NewTransfersServerTransport(&s.srv.TransfersServer) })
		resp, err = s.trTransfersServer.Do(req)
	default:
		err = fmt.Errorf("unhandled client %s", client)
	}

	if err != nil {
		return nil, err
	}

	return resp, nil
}

func initServer[T any](s *ServerFactoryTransport, dst **T, src func() *T) {
	s.trMu.Lock()
	if *dst == nil {
		*dst = src()
	}
	s.trMu.Unlock()
}
