package openstack

import (
	"fmt"
	"strings"

	"github.com/rackspace/gophercloud"
	identity2 "github.com/rackspace/gophercloud/openstack/identity/v2"
	endpoints3 "github.com/rackspace/gophercloud/openstack/identity/v3/endpoints"
	services3 "github.com/rackspace/gophercloud/openstack/identity/v3/services"
	tokens3 "github.com/rackspace/gophercloud/openstack/identity/v3/tokens"
	"github.com/rackspace/gophercloud/openstack/utils"
)

const (
	v20 = "v2.0"
	v30 = "v3.0"
)

// NewClient prepares an unauthenticated ProviderClient instance.
// Most users will probably prefer using the AuthenticatedClient function instead.
// This is useful if you wish to explicitly control the version of the identity service that's used for authentication explicitly,
// for example.
func NewClient(endpoint string) (*gophercloud.ProviderClient, error) {
	return &gophercloud.ProviderClient{IdentityEndpoint: endpoint}, nil
}

// AuthenticatedClient logs in to an OpenStack cloud found at the identity endpoint specified by options, acquires a token, and
// returns a Client instance that's ready to operate.
// It first queries the root identity endpoint to determine which versions of the identity service are supported, then chooses
// the most recent identity service available to proceed.
func AuthenticatedClient(options gophercloud.AuthOptions) (*gophercloud.ProviderClient, error) {
	client, err := NewClient(options.IdentityEndpoint)
	if err != nil {
		return nil, err
	}

	err = Authenticate(client, options)
	if err != nil {
		return nil, err
	}
	return client, nil
}

// Authenticate or re-authenticate against the most recent identity service supported at the provided endpoint.
func Authenticate(client *gophercloud.ProviderClient, options gophercloud.AuthOptions) error {
	versions := []*utils.Version{
		&utils.Version{ID: v20, Priority: 20},
		&utils.Version{ID: v30, Priority: 30},
	}

	chosen, endpoint, err := utils.ChooseVersion(client.IdentityEndpoint, versions)
	if err != nil {
		return err
	}

	if !strings.HasSuffix(endpoint, "/") {
		endpoint = endpoint + "/"
	}

	switch chosen.ID {
	case v20:
		v2Client := NewIdentityV2(client)
		v2Client.Endpoint = endpoint

		result, err := identity2.Authenticate(v2Client, options)
		if err != nil {
			return err
		}

		token, err := identity2.GetToken(result)
		if err != nil {
			return err
		}

		client.TokenID = token.ID
		client.EndpointLocator = func(opts gophercloud.EndpointOpts) (string, error) {
			return v2endpointLocator(result, opts)
		}

		return nil
	case v30:
		// Override the generated service endpoint with the one returned by the version endpoint.
		v3Client := NewIdentityV3(client)
		v3Client.Endpoint = endpoint

		result, err := tokens3.Create(v3Client, options, nil)
		if err != nil {
			return err
		}

		client.TokenID, err = result.TokenID()
		if err != nil {
			return err
		}
		client.EndpointLocator = func(opts gophercloud.EndpointOpts) (string, error) {
			return v3endpointLocator(v3Client, opts)
		}

		return nil
	default:
		// The switch statement must be out of date from the versions list.
		return fmt.Errorf("Unrecognized identity version: %s", chosen.ID)
	}
}

func v2endpointLocator(authResults identity2.AuthResults, opts gophercloud.EndpointOpts) (string, error) {
	catalog, err := identity2.GetServiceCatalog(authResults)
	if err != nil {
		return "", err
	}

	entries, err := catalog.CatalogEntries()
	if err != nil {
		return "", err
	}

	// Extract Endpoints from the catalog entries that match the requested Type, Name if provided, and Region if provided.
	var endpoints = make([]identity2.Endpoint, 0, 6)
	for _, entry := range entries {
		matched := true

		if entry.Type != opts.Type {
			matched = false
		}

		if opts.Name != "" && entry.Name != opts.Name {
			matched = false
		}

		if matched {
			for _, endpoint := range entry.Endpoints {
				if opts.Region == "" || endpoint.Region == opts.Region {
					endpoints = append(endpoints, endpoint)
				}
			}
		}
	}

	// Report an error if the options were ambiguous.
	if len(endpoints) == 0 {
		return "", gophercloud.ErrEndpointNotFound
	}
	if len(endpoints) > 1 {
		return "", fmt.Errorf("Discovered %d matching endpoints: %#v", len(endpoints), endpoints)
	}

	// Extract the appropriate URL from the matching Endpoint.
	for _, endpoint := range endpoints {
		switch opts.URLType {
		case "public", "":
			return endpoint.PublicURL, nil
		case "private":
			return endpoint.InternalURL, nil
		default:
			return "", fmt.Errorf("Unexpected URLType in endpoint query: %s", opts.URLType)
		}
	}

	return "", gophercloud.ErrEndpointNotFound
}

func v3endpointLocator(v3Client *gophercloud.ServiceClient, opts gophercloud.EndpointOpts) (string, error) {
	// Transform URLType into an Interface.
	var endpointInterface = endpoints3.InterfacePublic
	switch opts.URLType {
	case "", "public":
		endpointInterface = endpoints3.InterfacePublic
	case "internal":
		endpointInterface = endpoints3.InterfaceInternal
	case "admin":
		endpointInterface = endpoints3.InterfaceAdmin
	default:
		return "", fmt.Errorf("Unrecognized URLType: %s", opts.URLType)
	}

	// Discover the service we're interested in.
	serviceResults, err := services3.List(v3Client, services3.ListOpts{ServiceType: opts.Type})
	if err != nil {
		return "", err
	}

	allServiceResults, err := gophercloud.AllPages(serviceResults)
	if err != nil {
		return "", err
	}
	allServices := services3.AsServices(allServiceResults)

	if opts.Name != "" {
		filtered := make([]services3.Service, 0, 1)
		for _, service := range allServices {
			if service.Name == opts.Name {
				filtered = append(filtered, service)
			}
		}
		allServices = filtered
	}

	if len(allServices) == 0 {
		return "", gophercloud.ErrServiceNotFound
	}
	if len(allServices) > 1 {
		return "", fmt.Errorf("Discovered %d matching services: %#v", len(allServices), allServices)
	}

	service := allServices[0]

	// Enumerate the endpoints available for this service.
	endpointResults, err := endpoints3.List(v3Client, endpoints3.ListOpts{
		Interface: endpointInterface,
		ServiceID: service.ID,
	})
	if err != nil {
		return "", err
	}
	allEndpoints, err := gophercloud.AllPages(endpointResults)
	if err != nil {
		return "", err
	}
	endpoints := endpoints3.AsEndpoints(allEndpoints)

	if opts.Name != "" {
		filtered := make([]endpoints3.Endpoint, 0, 1)
		for _, endpoint := range endpoints {
			if opts.Region == "" || endpoint.Region == opts.Region {
				filtered = append(filtered, endpoint)
			}
		}
		endpoints = filtered
	}

	if len(endpoints) == 0 {
		return "", gophercloud.ErrEndpointNotFound
	}
	if len(endpoints) > 1 {
		return "", fmt.Errorf("Discovered %d matching endpoints: %#v", len(endpoints), endpoints)
	}

	endpoint := endpoints[0]

	return endpoint.URL, nil
}

// NewIdentityV2 creates a ServiceClient that may be used to interact with the v2 identity service.
func NewIdentityV2(client *gophercloud.ProviderClient) *gophercloud.ServiceClient {
	v2Endpoint := client.IdentityEndpoint + "/v2.0/"

	return &gophercloud.ServiceClient{
		Provider: client,
		Endpoint: v2Endpoint,
	}
}

// NewIdentityV3 creates a ServiceClient that may be used to access the v3 identity service.
func NewIdentityV3(client *gophercloud.ProviderClient) *gophercloud.ServiceClient {
	v3Endpoint := client.IdentityEndpoint + "/v3/"

	return &gophercloud.ServiceClient{
		Provider: client,
		Endpoint: v3Endpoint,
	}
}

// NewStorageV1 creates a ServiceClient that may be used with the v1 object storage package.
func NewStorageV1(client *gophercloud.ProviderClient, region string) (*gophercloud.ServiceClient, error) {
	url, err := client.EndpointLocator(gophercloud.EndpointOpts{Type: "object-store", Name: "swift"})
	if err != nil {
		return nil, err
	}
	return &gophercloud.ServiceClient{Provider: client, Endpoint: url}, nil
}
