//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"
	"github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
	"net/http"
	"strings"
	"sync"
)

// ServerFactory is a fake server for instances of the armbilling.ClientFactory type.
type ServerFactory struct {
	AccountsServer           AccountsServer
	AddressServer            AddressServer
	AgreementsServer         AgreementsServer
	AvailableBalancesServer  AvailableBalancesServer
	CustomersServer          CustomersServer
	EnrollmentAccountsServer EnrollmentAccountsServer
	InstructionsServer       InstructionsServer
	InvoiceSectionsServer    InvoiceSectionsServer
	InvoicesServer           InvoicesServer
	OperationsServer         OperationsServer
	PeriodsServer            PeriodsServer
	PermissionsServer        PermissionsServer
	PoliciesServer           PoliciesServer
	ProductsServer           ProductsServer
	ProfilesServer           ProfilesServer
	PropertyServer           PropertyServer
	ReservationsServer       ReservationsServer
	RoleAssignmentsServer    RoleAssignmentsServer
	RoleDefinitionsServer    RoleDefinitionsServer
	SubscriptionsServer      SubscriptionsServer
	TransactionsServer       TransactionsServer
}

// 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
	trAvailableBalancesServer  *AvailableBalancesServerTransport
	trCustomersServer          *CustomersServerTransport
	trEnrollmentAccountsServer *EnrollmentAccountsServerTransport
	trInstructionsServer       *InstructionsServerTransport
	trInvoiceSectionsServer    *InvoiceSectionsServerTransport
	trInvoicesServer           *InvoicesServerTransport
	trOperationsServer         *OperationsServerTransport
	trPeriodsServer            *PeriodsServerTransport
	trPermissionsServer        *PermissionsServerTransport
	trPoliciesServer           *PoliciesServerTransport
	trProductsServer           *ProductsServerTransport
	trProfilesServer           *ProfilesServerTransport
	trPropertyServer           *PropertyServerTransport
	trReservationsServer       *ReservationsServerTransport
	trRoleAssignmentsServer    *RoleAssignmentsServerTransport
	trRoleDefinitionsServer    *RoleDefinitionsServerTransport
	trSubscriptionsServer      *SubscriptionsServerTransport
	trTransactionsServer       *TransactionsServerTransport
}

// 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 "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 "EnrollmentAccountsClient":
		initServer(s, &s.trEnrollmentAccountsServer, func() *EnrollmentAccountsServerTransport {
			return NewEnrollmentAccountsServerTransport(&s.srv.EnrollmentAccountsServer)
		})
		resp, err = s.trEnrollmentAccountsServer.Do(req)
	case "InstructionsClient":
		initServer(s, &s.trInstructionsServer, func() *InstructionsServerTransport { return NewInstructionsServerTransport(&s.srv.InstructionsServer) })
		resp, err = s.trInstructionsServer.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 "PeriodsClient":
		initServer(s, &s.trPeriodsServer, func() *PeriodsServerTransport { return NewPeriodsServerTransport(&s.srv.PeriodsServer) })
		resp, err = s.trPeriodsServer.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 "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 "RoleDefinitionsClient":
		initServer(s, &s.trRoleDefinitionsServer, func() *RoleDefinitionsServerTransport {
			return NewRoleDefinitionsServerTransport(&s.srv.RoleDefinitionsServer)
		})
		resp, err = s.trRoleDefinitionsServer.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)
	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()
}
