// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package storage

import (
	"context"
	"errors"
	"fmt"
	"time"

	storagepb "cloud.google.com/go/storage/internal/apiv2/stubs"
	"google.golang.org/api/iterator"
	raw "google.golang.org/api/storage/v1"
)

// HMACState is the state of the HMAC key.
//
// This type is EXPERIMENTAL and subject to change or removal without notice.
type HMACState string

const (
	// Active is the status for an active key that can be used to sign
	// requests.
	Active HMACState = "ACTIVE"

	// Inactive is the status for an inactive key thus requests signed by
	// this key will be denied.
	Inactive HMACState = "INACTIVE"

	// Deleted is the status for a key that is deleted.
	// Once in this state the key cannot key cannot be recovered
	// and does not count towards key limits. Deleted keys will be cleaned
	// up later.
	Deleted HMACState = "DELETED"
)

// HMACKey is the representation of a Google Cloud Storage HMAC key.
//
// HMAC keys are used to authenticate signed access to objects. To enable HMAC key
// authentication, please visit https://cloud.google.com/storage/docs/migrating.
//
// This type is EXPERIMENTAL and subject to change or removal without notice.
type HMACKey struct {
	// The HMAC's secret key.
	Secret string

	// AccessID is the ID of the HMAC key.
	AccessID string

	// Etag is the HTTP/1.1 Entity tag.
	Etag string

	// ID is the ID of the HMAC key, including the ProjectID and AccessID.
	ID string

	// ProjectID is the ID of the project that owns the
	// service account to which the key authenticates.
	ProjectID string

	// ServiceAccountEmail is the email address
	// of the key's associated service account.
	ServiceAccountEmail string

	// CreatedTime is the creation time of the HMAC key.
	CreatedTime time.Time

	// UpdatedTime is the last modification time of the HMAC key metadata.
	UpdatedTime time.Time

	// State is the state of the HMAC key.
	// It can be one of StateActive, StateInactive or StateDeleted.
	State HMACState
}

// HMACKeyHandle helps provide access and management for HMAC keys.
//
// This type is EXPERIMENTAL and subject to change or removal without notice.
type HMACKeyHandle struct {
	projectID string
	accessID  string
	retry     *retryConfig
	raw       *raw.ProjectsHmacKeysService
}

// HMACKeyHandle creates a handle that will be used for HMACKey operations.
//
// This method is EXPERIMENTAL and subject to change or removal without notice.
func (c *Client) HMACKeyHandle(projectID, accessID string) *HMACKeyHandle {
	return &HMACKeyHandle{
		projectID: projectID,
		accessID:  accessID,
		retry:     c.retry,
		raw:       raw.NewProjectsHmacKeysService(c.raw),
	}
}

// Get invokes an RPC to retrieve the HMAC key referenced by the
// HMACKeyHandle's accessID.
//
// Options such as UserProjectForHMACKeys can be used to set the
// userProject to be billed against for operations.
//
// This method is EXPERIMENTAL and subject to change or removal without notice.
func (hkh *HMACKeyHandle) Get(ctx context.Context, opts ...HMACKeyOption) (*HMACKey, error) {
	call := hkh.raw.Get(hkh.projectID, hkh.accessID)

	desc := new(hmacKeyDesc)
	for _, opt := range opts {
		opt.withHMACKeyDesc(desc)
	}
	if desc.userProjectID != "" {
		call = call.UserProject(desc.userProjectID)
	}

	setClientHeader(call.Header())

	var metadata *raw.HmacKeyMetadata
	var err error
	err = run(ctx, func() error {
		metadata, err = call.Context(ctx).Do()
		return err
	}, hkh.retry, true, setRetryHeaderHTTP(call))
	if err != nil {
		return nil, err
	}

	hk := &raw.HmacKey{
		Metadata: metadata,
	}
	return toHMACKeyFromRaw(hk, false)
}

// Delete invokes an RPC to delete the key referenced by accessID, on Google Cloud Storage.
// Only inactive HMAC keys can be deleted.
// After deletion, a key cannot be used to authenticate requests.
//
// This method is EXPERIMENTAL and subject to change or removal without notice.
func (hkh *HMACKeyHandle) Delete(ctx context.Context, opts ...HMACKeyOption) error {
	delCall := hkh.raw.Delete(hkh.projectID, hkh.accessID)
	desc := new(hmacKeyDesc)
	for _, opt := range opts {
		opt.withHMACKeyDesc(desc)
	}
	if desc.userProjectID != "" {
		delCall = delCall.UserProject(desc.userProjectID)
	}
	setClientHeader(delCall.Header())

	return run(ctx, func() error {
		return delCall.Context(ctx).Do()
	}, hkh.retry, true, setRetryHeaderHTTP(delCall))
}

func toHMACKeyFromRaw(hk *raw.HmacKey, updatedTimeCanBeNil bool) (*HMACKey, error) {
	hkmd := hk.Metadata
	if hkmd == nil {
		return nil, errors.New("field Metadata cannot be nil")
	}
	createdTime, err := time.Parse(time.RFC3339, hkmd.TimeCreated)
	if err != nil {
		return nil, fmt.Errorf("field CreatedTime: %v", err)
	}
	updatedTime, err := time.Parse(time.RFC3339, hkmd.Updated)
	if err != nil && !updatedTimeCanBeNil {
		return nil, fmt.Errorf("field UpdatedTime: %v", err)
	}

	hmKey := &HMACKey{
		AccessID:    hkmd.AccessId,
		Secret:      hk.Secret,
		Etag:        hkmd.Etag,
		ID:          hkmd.Id,
		State:       HMACState(hkmd.State),
		ProjectID:   hkmd.ProjectId,
		CreatedTime: createdTime,
		UpdatedTime: updatedTime,

		ServiceAccountEmail: hkmd.ServiceAccountEmail,
	}

	return hmKey, nil
}

func toHMACKeyFromProto(pbmd *storagepb.HmacKeyMetadata) *HMACKey {
	if pbmd == nil {
		return nil
	}

	return &HMACKey{
		AccessID:            pbmd.GetAccessId(),
		ID:                  pbmd.GetId(),
		State:               HMACState(pbmd.GetState()),
		ProjectID:           pbmd.GetProject(),
		CreatedTime:         convertProtoTime(pbmd.GetCreateTime()),
		UpdatedTime:         convertProtoTime(pbmd.GetUpdateTime()),
		ServiceAccountEmail: pbmd.GetServiceAccountEmail(),
	}
}

// CreateHMACKey invokes an RPC for Google Cloud Storage to create a new HMACKey.
//
// This method is EXPERIMENTAL and subject to change or removal without notice.
func (c *Client) CreateHMACKey(ctx context.Context, projectID, serviceAccountEmail string, opts ...HMACKeyOption) (*HMACKey, error) {
	if projectID == "" {
		return nil, errors.New("storage: expecting a non-blank projectID")
	}
	if serviceAccountEmail == "" {
		return nil, errors.New("storage: expecting a non-blank service account email")
	}

	svc := raw.NewProjectsHmacKeysService(c.raw)
	call := svc.Create(projectID, serviceAccountEmail)
	desc := new(hmacKeyDesc)
	for _, opt := range opts {
		opt.withHMACKeyDesc(desc)
	}
	if desc.userProjectID != "" {
		call = call.UserProject(desc.userProjectID)
	}

	setClientHeader(call.Header())

	var hk *raw.HmacKey

	if err := run(ctx, func() error {
		h, err := call.Context(ctx).Do()
		hk = h
		return err
	}, c.retry, false, setRetryHeaderHTTP(call)); err != nil {
		return nil, err
	}

	return toHMACKeyFromRaw(hk, true)
}

// HMACKeyAttrsToUpdate defines the attributes of an HMACKey that will be updated.
//
// This type is EXPERIMENTAL and subject to change or removal without notice.
type HMACKeyAttrsToUpdate struct {
	// State is required and must be either StateActive or StateInactive.
	State HMACState

	// Etag is an optional field and it is the HTTP/1.1 Entity tag.
	Etag string
}

// Update mutates the HMACKey referred to by accessID.
//
// This method is EXPERIMENTAL and subject to change or removal without notice.
func (h *HMACKeyHandle) Update(ctx context.Context, au HMACKeyAttrsToUpdate, opts ...HMACKeyOption) (*HMACKey, error) {
	if au.State != Active && au.State != Inactive {
		return nil, fmt.Errorf("storage: invalid state %q for update, must be either %q or %q", au.State, Active, Inactive)
	}

	call := h.raw.Update(h.projectID, h.accessID, &raw.HmacKeyMetadata{
		Etag:  au.Etag,
		State: string(au.State),
	})

	desc := new(hmacKeyDesc)
	for _, opt := range opts {
		opt.withHMACKeyDesc(desc)
	}
	if desc.userProjectID != "" {
		call = call.UserProject(desc.userProjectID)
	}
	setClientHeader(call.Header())

	var metadata *raw.HmacKeyMetadata
	var err error
	isIdempotent := len(au.Etag) > 0
	err = run(ctx, func() error {
		metadata, err = call.Context(ctx).Do()
		return err
	}, h.retry, isIdempotent, setRetryHeaderHTTP(call))

	if err != nil {
		return nil, err
	}
	hk := &raw.HmacKey{
		Metadata: metadata,
	}
	return toHMACKeyFromRaw(hk, false)
}

// An HMACKeysIterator is an iterator over HMACKeys.
//
// Note: This iterator is not safe for concurrent operations without explicit synchronization.
//
// This type is EXPERIMENTAL and subject to change or removal without notice.
type HMACKeysIterator struct {
	ctx       context.Context
	raw       *raw.ProjectsHmacKeysService
	projectID string
	hmacKeys  []*HMACKey
	pageInfo  *iterator.PageInfo
	nextFunc  func() error
	index     int
	desc      hmacKeyDesc
	retry     *retryConfig
}

// ListHMACKeys returns an iterator for listing HMACKeys.
//
// Note: This iterator is not safe for concurrent operations without explicit synchronization.
//
// This method is EXPERIMENTAL and subject to change or removal without notice.
func (c *Client) ListHMACKeys(ctx context.Context, projectID string, opts ...HMACKeyOption) *HMACKeysIterator {
	it := &HMACKeysIterator{
		ctx:       ctx,
		raw:       raw.NewProjectsHmacKeysService(c.raw),
		projectID: projectID,
		retry:     c.retry,
	}

	for _, opt := range opts {
		opt.withHMACKeyDesc(&it.desc)
	}

	it.pageInfo, it.nextFunc = iterator.NewPageInfo(
		it.fetch,
		func() int { return len(it.hmacKeys) - it.index },
		func() interface{} {
			prev := it.hmacKeys
			it.hmacKeys = it.hmacKeys[:0]
			it.index = 0
			return prev
		})
	return it
}

// Next returns the next result. Its second return value is iterator.Done if
// there are no more results. Once Next returns iterator.Done, all subsequent
// calls will return iterator.Done.
//
// Note: This iterator is not safe for concurrent operations without explicit synchronization.
//
// This method is EXPERIMENTAL and subject to change or removal without notice.
func (it *HMACKeysIterator) Next() (*HMACKey, error) {
	if err := it.nextFunc(); err != nil {
		return nil, err
	}

	key := it.hmacKeys[it.index]
	it.index++

	return key, nil
}

// PageInfo supports pagination. See the google.golang.org/api/iterator package for details.
//
// Note: This iterator is not safe for concurrent operations without explicit synchronization.
//
// This method is EXPERIMENTAL and subject to change or removal without notice.
func (it *HMACKeysIterator) PageInfo() *iterator.PageInfo { return it.pageInfo }

func (it *HMACKeysIterator) fetch(pageSize int, pageToken string) (token string, err error) {
	// TODO: Remove fetch method upon integration. This method is internalized into
	// httpStorageClient.ListHMACKeys() as it is the only caller.
	call := it.raw.List(it.projectID)
	setClientHeader(call.Header())
	if pageToken != "" {
		call = call.PageToken(pageToken)
	}
	if it.desc.showDeletedKeys {
		call = call.ShowDeletedKeys(true)
	}
	if it.desc.userProjectID != "" {
		call = call.UserProject(it.desc.userProjectID)
	}
	if it.desc.forServiceAccountEmail != "" {
		call = call.ServiceAccountEmail(it.desc.forServiceAccountEmail)
	}
	if pageSize > 0 {
		call = call.MaxResults(int64(pageSize))
	}

	ctx := it.ctx
	var resp *raw.HmacKeysMetadata
	err = run(it.ctx, func() error {
		resp, err = call.Context(ctx).Do()
		return err
	}, it.retry, true, setRetryHeaderHTTP(call))
	if err != nil {
		return "", err
	}

	for _, metadata := range resp.Items {
		hk := &raw.HmacKey{
			Metadata: metadata,
		}
		hkey, err := toHMACKeyFromRaw(hk, true)
		if err != nil {
			return "", err
		}
		it.hmacKeys = append(it.hmacKeys, hkey)
	}
	return resp.NextPageToken, nil
}

type hmacKeyDesc struct {
	forServiceAccountEmail string
	showDeletedKeys        bool
	userProjectID          string
}

// HMACKeyOption configures the behavior of HMACKey related methods and actions.
//
// This interface is EXPERIMENTAL and subject to change or removal without notice.
type HMACKeyOption interface {
	withHMACKeyDesc(*hmacKeyDesc)
}

type hmacKeyDescFunc func(*hmacKeyDesc)

func (hkdf hmacKeyDescFunc) withHMACKeyDesc(hkd *hmacKeyDesc) {
	hkdf(hkd)
}

// ForHMACKeyServiceAccountEmail returns HMAC Keys that are
// associated with the email address of a service account in the project.
//
// Only one service account email can be used as a filter, so if multiple
// of these options are applied, the last email to be set will be used.
//
// This option is EXPERIMENTAL and subject to change or removal without notice.
func ForHMACKeyServiceAccountEmail(serviceAccountEmail string) HMACKeyOption {
	return hmacKeyDescFunc(func(hkd *hmacKeyDesc) {
		hkd.forServiceAccountEmail = serviceAccountEmail
	})
}

// ShowDeletedHMACKeys will also list keys whose state is "DELETED".
//
// This option is EXPERIMENTAL and subject to change or removal without notice.
func ShowDeletedHMACKeys() HMACKeyOption {
	return hmacKeyDescFunc(func(hkd *hmacKeyDesc) {
		hkd.showDeletedKeys = true
	})
}

// UserProjectForHMACKeys will bill the request against userProjectID
// if userProjectID is non-empty.
//
// Note: This is a noop right now and only provided for API compatibility.
//
// This option is EXPERIMENTAL and subject to change or removal without notice.
func UserProjectForHMACKeys(userProjectID string) HMACKeyOption {
	return hmacKeyDescFunc(func(hkd *hmacKeyDesc) {
		hkd.userProjectID = userProjectID
	})
}
