package gophercloud

import (
	"net/http"
	"strings"
)

// Provider structures exist for each tangible provider of OpenStack service.
// For example, Rackspace, Hewlett-Packard, and NASA might have their own instance of this structure.
//
// At a minimum, a provider must expose an authentication endpoint.
type Provider struct {
	AuthEndpoint string
}

// ReauthHandlerFunc functions are responsible for somehow performing the task of
// reauthentication.
type ReauthHandlerFunc func(AccessProvider) error

// Context structures encapsulate Gophercloud-global state in a manner which
// facilitates easier unit testing.  As a user of this SDK, you'll never
// have to use this structure, except when contributing new code to the SDK.
type Context struct {
	// providerMap serves as a directory of supported providers.
	providerMap map[string]Provider

	// httpClient refers to the current HTTP client interface to use.
	httpClient *http.Client

	// reauthHandler provides the functionality needed to re-authenticate
	// if that feature is enabled.  Note: in order to allow for automatic
	// re-authentication, the Context object will need to remember your
	// username, password, and tenant ID as provided in the initial call
	// to Authenticate().  If you do not desire this, you'll need to handle
	// reauthentication yourself through other means.  Two methods exist:
	// the first approach is to just handle errors yourself at the application
	// layer, and the other is through a custom reauthentication handler
	// set through the WithReauthHandler() method.
	reauthHandler ReauthHandlerFunc
}

// TestContext yields a new Context instance, pre-initialized with a barren
// state suitable for per-unit-test customization.  This configuration consists
// of:
//
// * An empty provider map.
//
// * An HTTP client built by the net/http package (see http://godoc.org/net/http#Client).
func TestContext() *Context {
	return &Context{
		providerMap: make(map[string]Provider),
		httpClient:  &http.Client{},
		reauthHandler: func(acc AccessProvider) error {
			return acc.Reauthenticate()
		},
	}
}

// UseCustomClient configures the context to use a customized HTTP client
// instance.  By default, TestContext() will return a Context which uses
// the net/http package's default client instance.
func (c *Context) UseCustomClient(hc *http.Client) *Context {
	c.httpClient = hc
	return c
}

// RegisterProvider allows a unit test to register a mythical provider convenient for testing.
// If the provider structure lacks adequate configuration, or the configuration given has some
// detectable error, an ErrConfiguration error will result.
func (c *Context) RegisterProvider(name string, p Provider) error {
	if p.AuthEndpoint == "" {
		return ErrConfiguration
	}

	c.providerMap[name] = p
	return nil
}

// WithProvider offers convenience for unit tests.
func (c *Context) WithProvider(name string, p Provider) *Context {
	err := c.RegisterProvider(name, p)
	if err != nil {
		panic(err)
	}
	return c
}

// ProviderByName will locate a provider amongst those previously registered, if it exists.
// If the named provider has not been registered, an ErrProvider error will result.
//
// You may also specify a custom Identity API URL.
// Any provider name that contains the characters "://", in that order, will be treated as a custom Identity API URL.
// Custom URLs, important for private cloud deployments, overrides all provider configurations.
func (c *Context) ProviderByName(name string) (p Provider, err error) {
	for provider, descriptor := range c.providerMap {
		if name == provider {
			return descriptor, nil
		}
	}
	if strings.Contains(name, "://") {
		p = Provider {
			AuthEndpoint: name,
		}
		return p, nil
	}
	return Provider{}, ErrProvider
}

// Instantiates a Cloud Servers API for the provider given.
func (c *Context) ServersApi(acc AccessProvider, criteria ApiCriteria) (CloudServersProvider, error) {
	url := acc.FirstEndpointUrlByCriteria(criteria)
	if url == "" {
		return nil, ErrEndpoint
	}

	gcp := &genericServersProvider{
		endpoint: url,
		context:  c,
		access:   acc,
	}

	return gcp, nil
}

// WithReauthHandler configures the context to handle reauthentication attempts using the supplied
// funtion.  By default, reauthentication happens by invoking Authenticate(), which is unlikely to be
// useful in a unit test.
//
// Do not confuse this function with WithReauth()!  Although they work together to support reauthentication,
// WithReauth() actually contains the decision-making logic to determine when to perform a reauth,
// while WithReauthHandler() is used to configure what a reauth actually entails.
func (c *Context) WithReauthHandler(f ReauthHandlerFunc) *Context {
	c.reauthHandler = f
	return c
}
