// Copyright 2015 The etcd Authors
//
// 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 client

import (
	"bytes"
	"context"
	"encoding/json"
	"net/http"
	"net/url"
)

type Role struct {
	Role        string       `json:"role"`
	Permissions Permissions  `json:"permissions"`
	Grant       *Permissions `json:"grant,omitempty"`
	Revoke      *Permissions `json:"revoke,omitempty"`
}

type Permissions struct {
	KV rwPermission `json:"kv"`
}

type rwPermission struct {
	Read  []string `json:"read"`
	Write []string `json:"write"`
}

type PermissionType int

const (
	ReadPermission PermissionType = iota
	WritePermission
	ReadWritePermission
)

// NewAuthRoleAPI constructs a new AuthRoleAPI that uses HTTP to
// interact with etcd's role creation and modification features.
func NewAuthRoleAPI(c Client) AuthRoleAPI {
	return &httpAuthRoleAPI{
		client: c,
	}
}

type AuthRoleAPI interface {
	// AddRole adds a role.
	AddRole(ctx context.Context, role string) error

	// RemoveRole removes a role.
	RemoveRole(ctx context.Context, role string) error

	// GetRole retrieves role details.
	GetRole(ctx context.Context, role string) (*Role, error)

	// GrantRoleKV grants a role some permission prefixes for the KV store.
	GrantRoleKV(ctx context.Context, role string, prefixes []string, permType PermissionType) (*Role, error)

	// RevokeRoleKV revokes some permission prefixes for a role on the KV store.
	RevokeRoleKV(ctx context.Context, role string, prefixes []string, permType PermissionType) (*Role, error)

	// ListRoles lists roles.
	ListRoles(ctx context.Context) ([]string, error)
}

type httpAuthRoleAPI struct {
	client httpClient
}

type authRoleAPIAction struct {
	verb string
	name string
	role *Role
}

type authRoleAPIList struct{}

func (list *authRoleAPIList) HTTPRequest(ep url.URL) *http.Request {
	u := v2AuthURL(ep, "roles", "")
	req, _ := http.NewRequest("GET", u.String(), nil)
	req.Header.Set("Content-Type", "application/json")
	return req
}

func (l *authRoleAPIAction) HTTPRequest(ep url.URL) *http.Request {
	u := v2AuthURL(ep, "roles", l.name)
	if l.role == nil {
		req, _ := http.NewRequest(l.verb, u.String(), nil)
		return req
	}
	b, err := json.Marshal(l.role)
	if err != nil {
		panic(err)
	}
	body := bytes.NewReader(b)
	req, _ := http.NewRequest(l.verb, u.String(), body)
	req.Header.Set("Content-Type", "application/json")
	return req
}

func (r *httpAuthRoleAPI) ListRoles(ctx context.Context) ([]string, error) {
	resp, body, err := r.client.Do(ctx, &authRoleAPIList{})
	if err != nil {
		return nil, err
	}
	if err = assertStatusCode(resp.StatusCode, http.StatusOK); err != nil {
		return nil, err
	}
	var roleList struct {
		Roles []Role `json:"roles"`
	}
	if err = json.Unmarshal(body, &roleList); err != nil {
		return nil, err
	}
	ret := make([]string, 0, len(roleList.Roles))
	for _, r := range roleList.Roles {
		ret = append(ret, r.Role)
	}
	return ret, nil
}

func (r *httpAuthRoleAPI) AddRole(ctx context.Context, rolename string) error {
	role := &Role{
		Role: rolename,
	}
	return r.addRemoveRole(ctx, &authRoleAPIAction{
		verb: "PUT",
		name: rolename,
		role: role,
	})
}

func (r *httpAuthRoleAPI) RemoveRole(ctx context.Context, rolename string) error {
	return r.addRemoveRole(ctx, &authRoleAPIAction{
		verb: "DELETE",
		name: rolename,
	})
}

func (r *httpAuthRoleAPI) addRemoveRole(ctx context.Context, req *authRoleAPIAction) error {
	resp, body, err := r.client.Do(ctx, req)
	if err != nil {
		return err
	}
	if err := assertStatusCode(resp.StatusCode, http.StatusOK, http.StatusCreated); err != nil {
		var sec authError
		err := json.Unmarshal(body, &sec)
		if err != nil {
			return err
		}
		return sec
	}
	return nil
}

func (r *httpAuthRoleAPI) GetRole(ctx context.Context, rolename string) (*Role, error) {
	return r.modRole(ctx, &authRoleAPIAction{
		verb: "GET",
		name: rolename,
	})
}

func buildRWPermission(prefixes []string, permType PermissionType) rwPermission {
	var out rwPermission
	switch permType {
	case ReadPermission:
		out.Read = prefixes
	case WritePermission:
		out.Write = prefixes
	case ReadWritePermission:
		out.Read = prefixes
		out.Write = prefixes
	}
	return out
}

func (r *httpAuthRoleAPI) GrantRoleKV(ctx context.Context, rolename string, prefixes []string, permType PermissionType) (*Role, error) {
	rwp := buildRWPermission(prefixes, permType)
	role := &Role{
		Role: rolename,
		Grant: &Permissions{
			KV: rwp,
		},
	}
	return r.modRole(ctx, &authRoleAPIAction{
		verb: "PUT",
		name: rolename,
		role: role,
	})
}

func (r *httpAuthRoleAPI) RevokeRoleKV(ctx context.Context, rolename string, prefixes []string, permType PermissionType) (*Role, error) {
	rwp := buildRWPermission(prefixes, permType)
	role := &Role{
		Role: rolename,
		Revoke: &Permissions{
			KV: rwp,
		},
	}
	return r.modRole(ctx, &authRoleAPIAction{
		verb: "PUT",
		name: rolename,
		role: role,
	})
}

func (r *httpAuthRoleAPI) modRole(ctx context.Context, req *authRoleAPIAction) (*Role, error) {
	resp, body, err := r.client.Do(ctx, req)
	if err != nil {
		return nil, err
	}
	if err = assertStatusCode(resp.StatusCode, http.StatusOK); err != nil {
		var sec authError
		err = json.Unmarshal(body, &sec)
		if err != nil {
			return nil, err
		}
		return nil, sec
	}
	var role Role
	if err = json.Unmarshal(body, &role); err != nil {
		return nil, err
	}
	return &role, nil
}
