//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 armpanngfw.ClientFactory type.
type ServerFactory struct {
	CertificateObjectGlobalRulestackServer CertificateObjectGlobalRulestackServer
	CertificateObjectLocalRulestackServer  CertificateObjectLocalRulestackServer
	FirewallStatusServer                   FirewallStatusServer
	FirewallsServer                        FirewallsServer
	FqdnListGlobalRulestackServer          FqdnListGlobalRulestackServer
	FqdnListLocalRulestackServer           FqdnListLocalRulestackServer
	GlobalRulestackServer                  GlobalRulestackServer
	LocalRulesServer                       LocalRulesServer
	LocalRulestacksServer                  LocalRulestacksServer
	OperationsServer                       OperationsServer
	PostRulesServer                        PostRulesServer
	PreRulesServer                         PreRulesServer
	PrefixListGlobalRulestackServer        PrefixListGlobalRulestackServer
	PrefixListLocalRulestackServer         PrefixListLocalRulestackServer
}

// NewServerFactoryTransport creates a new instance of ServerFactoryTransport with the provided implementation.
// The returned ServerFactoryTransport instance is connected to an instance of armpanngfw.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 armpanngfw.ClientFactory to instances of ServerFactory.
// Don't use this type directly, use NewServerFactoryTransport instead.
type ServerFactoryTransport struct {
	srv                                      *ServerFactory
	trMu                                     sync.Mutex
	trCertificateObjectGlobalRulestackServer *CertificateObjectGlobalRulestackServerTransport
	trCertificateObjectLocalRulestackServer  *CertificateObjectLocalRulestackServerTransport
	trFirewallStatusServer                   *FirewallStatusServerTransport
	trFirewallsServer                        *FirewallsServerTransport
	trFqdnListGlobalRulestackServer          *FqdnListGlobalRulestackServerTransport
	trFqdnListLocalRulestackServer           *FqdnListLocalRulestackServerTransport
	trGlobalRulestackServer                  *GlobalRulestackServerTransport
	trLocalRulesServer                       *LocalRulesServerTransport
	trLocalRulestacksServer                  *LocalRulestacksServerTransport
	trOperationsServer                       *OperationsServerTransport
	trPostRulesServer                        *PostRulesServerTransport
	trPreRulesServer                         *PreRulesServerTransport
	trPrefixListGlobalRulestackServer        *PrefixListGlobalRulestackServerTransport
	trPrefixListLocalRulestackServer         *PrefixListLocalRulestackServerTransport
}

// 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 "CertificateObjectGlobalRulestackClient":
		initServer(s, &s.trCertificateObjectGlobalRulestackServer, func() *CertificateObjectGlobalRulestackServerTransport {
			return NewCertificateObjectGlobalRulestackServerTransport(&s.srv.CertificateObjectGlobalRulestackServer)
		})
		resp, err = s.trCertificateObjectGlobalRulestackServer.Do(req)
	case "CertificateObjectLocalRulestackClient":
		initServer(s, &s.trCertificateObjectLocalRulestackServer, func() *CertificateObjectLocalRulestackServerTransport {
			return NewCertificateObjectLocalRulestackServerTransport(&s.srv.CertificateObjectLocalRulestackServer)
		})
		resp, err = s.trCertificateObjectLocalRulestackServer.Do(req)
	case "FirewallStatusClient":
		initServer(s, &s.trFirewallStatusServer, func() *FirewallStatusServerTransport {
			return NewFirewallStatusServerTransport(&s.srv.FirewallStatusServer)
		})
		resp, err = s.trFirewallStatusServer.Do(req)
	case "FirewallsClient":
		initServer(s, &s.trFirewallsServer, func() *FirewallsServerTransport { return NewFirewallsServerTransport(&s.srv.FirewallsServer) })
		resp, err = s.trFirewallsServer.Do(req)
	case "FqdnListGlobalRulestackClient":
		initServer(s, &s.trFqdnListGlobalRulestackServer, func() *FqdnListGlobalRulestackServerTransport {
			return NewFqdnListGlobalRulestackServerTransport(&s.srv.FqdnListGlobalRulestackServer)
		})
		resp, err = s.trFqdnListGlobalRulestackServer.Do(req)
	case "FqdnListLocalRulestackClient":
		initServer(s, &s.trFqdnListLocalRulestackServer, func() *FqdnListLocalRulestackServerTransport {
			return NewFqdnListLocalRulestackServerTransport(&s.srv.FqdnListLocalRulestackServer)
		})
		resp, err = s.trFqdnListLocalRulestackServer.Do(req)
	case "GlobalRulestackClient":
		initServer(s, &s.trGlobalRulestackServer, func() *GlobalRulestackServerTransport {
			return NewGlobalRulestackServerTransport(&s.srv.GlobalRulestackServer)
		})
		resp, err = s.trGlobalRulestackServer.Do(req)
	case "LocalRulesClient":
		initServer(s, &s.trLocalRulesServer, func() *LocalRulesServerTransport { return NewLocalRulesServerTransport(&s.srv.LocalRulesServer) })
		resp, err = s.trLocalRulesServer.Do(req)
	case "LocalRulestacksClient":
		initServer(s, &s.trLocalRulestacksServer, func() *LocalRulestacksServerTransport {
			return NewLocalRulestacksServerTransport(&s.srv.LocalRulestacksServer)
		})
		resp, err = s.trLocalRulestacksServer.Do(req)
	case "OperationsClient":
		initServer(s, &s.trOperationsServer, func() *OperationsServerTransport { return NewOperationsServerTransport(&s.srv.OperationsServer) })
		resp, err = s.trOperationsServer.Do(req)
	case "PostRulesClient":
		initServer(s, &s.trPostRulesServer, func() *PostRulesServerTransport { return NewPostRulesServerTransport(&s.srv.PostRulesServer) })
		resp, err = s.trPostRulesServer.Do(req)
	case "PreRulesClient":
		initServer(s, &s.trPreRulesServer, func() *PreRulesServerTransport { return NewPreRulesServerTransport(&s.srv.PreRulesServer) })
		resp, err = s.trPreRulesServer.Do(req)
	case "PrefixListGlobalRulestackClient":
		initServer(s, &s.trPrefixListGlobalRulestackServer, func() *PrefixListGlobalRulestackServerTransport {
			return NewPrefixListGlobalRulestackServerTransport(&s.srv.PrefixListGlobalRulestackServer)
		})
		resp, err = s.trPrefixListGlobalRulestackServer.Do(req)
	case "PrefixListLocalRulestackClient":
		initServer(s, &s.trPrefixListLocalRulestackServer, func() *PrefixListLocalRulestackServerTransport {
			return NewPrefixListLocalRulestackServerTransport(&s.srv.PrefixListLocalRulestackServer)
		})
		resp, err = s.trPrefixListLocalRulestackServer.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()
}
