package gophercloud

import (
	"github.com/racker/perigee"
)

// AuthOptions lets anyone calling Authenticate() supply the required access credentials.
// At present, only Identity V2 API support exists; therefore, only Username, Password,
// and optionally, TenantId are provided.  If future Identity API versions become available,
// alternative fields unique to those versions may appear here.
type AuthOptions struct {
	// Username and Password are required if using Identity V2 API.
	// Consult with your provider's control panel to discover your
	// account's username and password.
	Username, Password string

	// ApiKey used for providers that support Api Key authentication
	ApiKey string

	// The TenantId field is optional for the Identity V2 API.
	TenantId string

	// The TenantName can be specified instead of the TenantId
	TenantName string

	// AllowReauth should be set to true if you grant permission for Gophercloud to cache
	// your credentials in memory, and to allow Gophercloud to attempt to re-authenticate
	// automatically if/when your token expires.  If you set it to false, it will not cache
	// these settings, but re-authentication will not be possible.  This setting defaults
	// to false.
	AllowReauth bool
}

// AuthContainer provides a JSON encoding wrapper for passing credentials to the Identity
// service.  You will not work with this structure directly.
type AuthContainer struct {
	Auth Auth `json:"auth"`
}

// Auth provides a JSON encoding wrapper for passing credentials to the Identity
// service.  You will not work with this structure directly.
type Auth struct {
	PasswordCredentials *PasswordCredentials `json:"passwordCredentials,omitempty"`
	ApiKeyCredentials   *ApiKeyCredentials   `json:"RAX-KSKEY:apiKeyCredentials,omitempty"`
	TenantId            string               `json:"tenantId,omitempty"`
	TenantName          string               `json:"tenantName,omitempty"`
}

// PasswordCredentials provides a JSON encoding wrapper for passing credentials to the Identity
// service.  You will not work with this structure directly.
type PasswordCredentials struct {
	Username string `json:"username"`
	Password string `json:"password"`
}

type ApiKeyCredentials struct {
	Username string `json:"username"`
	ApiKey   string `json:"apiKey"`
}

// Access encapsulates the API token and its relevant fields, as well as the
// services catalog that Identity API returns once authenticated.
type Access struct {
	Token          Token
	ServiceCatalog []CatalogEntry
	User           User
	provider       Provider    `json:"-"`
	options        AuthOptions `json:"-"`
	context        *Context    `json:"-"`
}

// Token encapsulates an authentication token and when it expires.  It also includes
// tenant information if available.
type Token struct {
	Id, Expires string
	Tenant      Tenant
}

// Tenant encapsulates tenant authentication information.  If, after authentication,
// no tenant information is supplied, both Id and Name will be "".
type Tenant struct {
	Id, Name string
}

// User encapsulates the user credentials, and provides visibility in what
// the user can do through its role assignments.
type User struct {
	Id, Name          string
	XRaxDefaultRegion string `json:"RAX-AUTH:defaultRegion"`
	Roles             []Role
}

// Role encapsulates a permission that a user can rely on.
type Role struct {
	Description, Id, Name string
}

// CatalogEntry encapsulates a service catalog record.
type CatalogEntry struct {
	Name, Type string
	Endpoints  []EntryEndpoint
}

// EntryEndpoint encapsulates how to get to the API of some service.
type EntryEndpoint struct {
	Region, TenantId                    string
	PublicURL, InternalURL              string
	VersionId, VersionInfo, VersionList string
}

//
func getAuthCredentials(options AuthOptions) Auth {
	if options.ApiKey == "" {
		return Auth{
			PasswordCredentials: &PasswordCredentials{
				Username: options.Username,
				Password: options.Password,
			},
			TenantId:   options.TenantId,
			TenantName: options.TenantName,
		}
	} else {
		return Auth{
			ApiKeyCredentials: &ApiKeyCredentials{
				Username: options.Username,
				ApiKey:   options.ApiKey,
			},
			TenantId:   options.TenantId,
			TenantName: options.TenantName,
		}
	}
}

// papersPlease contains the common logic between authentication and re-authentication.
// The name, obviously a joke on the process of authentication, was chosen because
// of how many other entities exist in the program containing the word Auth or Authorization.
// I didn't need another one.
func (c *Context) papersPlease(p Provider, options AuthOptions) (*Access, error) {
	var access *Access

	if (options.Username == "") || (options.Password == "" && options.ApiKey == "") {
		return nil, ErrCredentials
	}

	err := perigee.Post(p.AuthEndpoint, perigee.Options{
		CustomClient: c.httpClient,
		ReqBody: &AuthContainer{
			Auth: getAuthCredentials(options),
		},
		Results: &struct {
			Access **Access `json:"access"`
		}{
			&access,
		},
	})
	if err == nil {
		access.options = options
		access.provider = p
		access.context = c
	}
	return access, err
}

// Authenticate() grants access to the OpenStack-compatible provider API.
//
// Providers are identified through a unique key string.
// See the RegisterProvider() method for more details.
//
// The supplied AuthOptions instance allows the client to specify only those credentials
// relevant for the authentication request.  At present, support exists for OpenStack
// Identity V2 API only; support for V3 will become available as soon as documentation for it
// becomes readily available.
//
// For Identity V2 API requirements, you must provide at least the Username and Password
// options.  The TenantId field is optional, and defaults to "".
func (c *Context) Authenticate(provider string, options AuthOptions) (*Access, error) {
	p, err := c.ProviderByName(provider)
	if err != nil {
		return nil, err
	}
	return c.papersPlease(p, options)
}

// Reauthenticate attempts to reauthenticate using the configured access credentials, if
// allowed.  This method takes no action unless your AuthOptions has the AllowReauth flag
// set to true.
func (a *Access) Reauthenticate() error {
	var other *Access
	var err error

	if a.options.AllowReauth {
		other, err = a.context.papersPlease(a.provider, a.options)
		if err == nil {
			*a = *other
		}
	}
	return err
}

// See AccessProvider interface definition for details.
func (a *Access) FirstEndpointUrlByCriteria(ac ApiCriteria) string {
	ep := FindFirstEndpointByCriteria(a.ServiceCatalog, ac)
	urls := []string{ep.PublicURL, ep.InternalURL}
	return urls[ac.UrlChoice]
}

// See AccessProvider interface definition for details.
func (a *Access) AuthToken() string {
	return a.Token.Id
}

// See AccessProvider interface definition for details.
func (a *Access) Revoke(tok string) error {
	url := a.provider.AuthEndpoint + "/" + tok
	err := perigee.Delete(url, perigee.Options{
		MoreHeaders: map[string]string{
			"X-Auth-Token": a.AuthToken(),
		},
		OkCodes: []int{204},
	})
	return err
}

// See ServiceCatalogerForIdentityV2 interface definition for details.
// Note that the raw slice is returend; be careful not to alter the fields of any members,
// for other components of Gophercloud may depend upon them.
// If this becomes a problem in the future,
// a future revision may return a deep-copy of the service catalog instead.
func (a *Access) V2ServiceCatalog() []CatalogEntry {
	return a.ServiceCatalog
}
