// Copyright 2020 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 bigquery

import (
	"context"
	"errors"
	"fmt"

	"cloud.google.com/go/iam"
	"cloud.google.com/go/internal/trace"
	bq "google.golang.org/api/bigquery/v2"
	iampb "google.golang.org/genproto/googleapis/iam/v1"
)

// IAM provides access to an iam.Handle that allows access to IAM functionality for
// the given BigQuery table.  For more information, see
// https://pkg.go.dev/cloud.google.com/go/iam
func (t *Table) IAM() *iam.Handle {
	return iam.InternalNewHandleClient(&bqIAMClient{
		bqs: t.c.bqs,
	}, fmt.Sprintf("projects/%s/datasets/%s/tables/%s",
		t.ProjectID, t.DatasetID, t.TableID))
}

// bqIAMClient is a client that satisfies the IAM "client" interface.
//
// This client has an explicit assumption that it's only working with Table resources.
type bqIAMClient struct {
	bqs *bq.Service
}

func (c *bqIAMClient) Get(ctx context.Context, resource string) (p *iampb.Policy, err error) {
	return c.GetWithVersion(ctx, resource, 1)
}

func (c *bqIAMClient) GetWithVersion(ctx context.Context, resource string, requestedPolicyVersion int32) (p *iampb.Policy, err error) {
	if requestedPolicyVersion > 1 {
		return nil, errors.New("bigquery: only IAM policy version 1 is supported")
	}
	ctx = trace.StartSpan(ctx, "cloud.google.com/go/bigquery.IAM.Get")
	defer func() { trace.EndSpan(ctx, err) }()

	iamReq := &bq.GetIamPolicyRequest{
		Options: &bq.GetPolicyOptions{
			RequestedPolicyVersion: int64(requestedPolicyVersion),
		},
	}
	call := c.bqs.Tables.GetIamPolicy(resource, iamReq)
	setClientHeader(call.Header())

	var bqp *bq.Policy
	err = runWithRetry(ctx, func() error {
		bqp, err = call.Context(ctx).Do()
		return err
	})
	if err != nil {
		return nil, err
	}
	return iamFromBigQueryPolicy(bqp), nil
}

func (c *bqIAMClient) Set(ctx context.Context, resource string, p *iampb.Policy) (err error) {
	ctx = trace.StartSpan(ctx, "cloud.google.com/go/bigquery.IAM.Set")
	defer func() { trace.EndSpan(ctx, err) }()

	bqp := iamToBigQueryPolicy(p)
	call := c.bqs.Tables.SetIamPolicy(resource, &bq.SetIamPolicyRequest{Policy: bqp})
	setClientHeader(call.Header())
	return runWithRetry(ctx, func() error {
		_, err := call.Context(ctx).Do()
		return err
	})
}

func (c *bqIAMClient) Test(ctx context.Context, resource string, perms []string) (p []string, err error) {
	ctx = trace.StartSpan(ctx, "cloud.google.com/go/bigquery.IAM.Test")
	defer func() { trace.EndSpan(ctx, err) }()

	call := c.bqs.Tables.TestIamPermissions(resource, &bq.TestIamPermissionsRequest{Permissions: perms})
	setClientHeader(call.Header())

	var res *bq.TestIamPermissionsResponse
	err = runWithRetry(ctx, func() error {
		res, err = call.Context(ctx).Do()
		return err
	})
	if err != nil {
		return nil, err
	}
	return res.Permissions, nil
}

func iamToBigQueryPolicy(ip *iampb.Policy) *bq.Policy {
	return &bq.Policy{
		Bindings: iamToBigQueryBindings(ip.Bindings),
		Etag:     string(ip.Etag),
		Version:  int64(ip.Version),
	}
}

func iamToBigQueryBindings(ibs []*iampb.Binding) []*bq.Binding {
	var bqBindings []*bq.Binding
	for _, ib := range ibs {
		bqBindings = append(bqBindings, &bq.Binding{
			Role:    ib.Role,
			Members: ib.Members,
		})
	}
	return bqBindings
}

func iamFromBigQueryPolicy(bqPolicy *bq.Policy) *iampb.Policy {
	return &iampb.Policy{
		Bindings: iamFromBigQueryBindings(bqPolicy.Bindings),
		Etag:     []byte(bqPolicy.Etag),
		Version:  int32(bqPolicy.Version),
	}
}

func iamFromBigQueryBindings(bqBindings []*bq.Binding) []*iampb.Binding {
	var ibs []*iampb.Binding
	for _, bqb := range bqBindings {
		ibs = append(ibs, &iampb.Binding{
			Role:    bqb.Role,
			Members: bqb.Members,
		})
	}
	return ibs
}
