// Copyright 2018 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 auth

import (
	"crypto/ecdsa"
	"crypto/rsa"
	"fmt"
	"io/ioutil"
	"time"

	jwt "github.com/dgrijalva/jwt-go"
)

const (
	optSignMethod = "sign-method"
	optPublicKey  = "pub-key"
	optPrivateKey = "priv-key"
	optTTL        = "ttl"
)

var knownOptions = map[string]bool{
	optSignMethod: true,
	optPublicKey:  true,
	optPrivateKey: true,
	optTTL:        true,
}

var (
	// DefaultTTL will be used when a 'ttl' is not specified
	DefaultTTL = 5 * time.Minute
)

type jwtOptions struct {
	SignMethod jwt.SigningMethod
	PublicKey  []byte
	PrivateKey []byte
	TTL        time.Duration
}

// ParseWithDefaults will load options from the specified map or set defaults where appropriate
func (opts *jwtOptions) ParseWithDefaults(optMap map[string]string) error {
	if opts.TTL == 0 && optMap[optTTL] == "" {
		opts.TTL = DefaultTTL
	}

	return opts.Parse(optMap)
}

// Parse will load options from the specified map
func (opts *jwtOptions) Parse(optMap map[string]string) error {
	var err error
	if ttl := optMap[optTTL]; ttl != "" {
		opts.TTL, err = time.ParseDuration(ttl)
		if err != nil {
			return err
		}
	}

	if file := optMap[optPublicKey]; file != "" {
		opts.PublicKey, err = ioutil.ReadFile(file)
		if err != nil {
			return err
		}
	}

	if file := optMap[optPrivateKey]; file != "" {
		opts.PrivateKey, err = ioutil.ReadFile(file)
		if err != nil {
			return err
		}
	}

	// signing method is a required field
	method := optMap[optSignMethod]
	opts.SignMethod = jwt.GetSigningMethod(method)
	if opts.SignMethod == nil {
		return ErrInvalidAuthMethod
	}

	return nil
}

// Key will parse and return the appropriately typed key for the selected signature method
func (opts *jwtOptions) Key() (interface{}, error) {
	switch opts.SignMethod.(type) {
	case *jwt.SigningMethodRSA, *jwt.SigningMethodRSAPSS:
		return opts.rsaKey()
	case *jwt.SigningMethodECDSA:
		return opts.ecKey()
	case *jwt.SigningMethodHMAC:
		return opts.hmacKey()
	default:
		return nil, fmt.Errorf("unsupported signing method: %T", opts.SignMethod)
	}
}

func (opts *jwtOptions) hmacKey() (interface{}, error) {
	if len(opts.PrivateKey) == 0 {
		return nil, ErrMissingKey
	}
	return opts.PrivateKey, nil
}

func (opts *jwtOptions) rsaKey() (interface{}, error) {
	var (
		priv *rsa.PrivateKey
		pub  *rsa.PublicKey
		err  error
	)

	if len(opts.PrivateKey) > 0 {
		priv, err = jwt.ParseRSAPrivateKeyFromPEM(opts.PrivateKey)
		if err != nil {
			return nil, err
		}
	}

	if len(opts.PublicKey) > 0 {
		pub, err = jwt.ParseRSAPublicKeyFromPEM(opts.PublicKey)
		if err != nil {
			return nil, err
		}
	}

	if priv == nil {
		if pub == nil {
			// Neither key given
			return nil, ErrMissingKey
		}
		// Public key only, can verify tokens
		return pub, nil
	}

	// both keys provided, make sure they match
	if pub != nil && pub.E != priv.E && pub.N.Cmp(priv.N) != 0 {
		return nil, ErrKeyMismatch
	}

	return priv, nil
}

func (opts *jwtOptions) ecKey() (interface{}, error) {
	var (
		priv *ecdsa.PrivateKey
		pub  *ecdsa.PublicKey
		err  error
	)

	if len(opts.PrivateKey) > 0 {
		priv, err = jwt.ParseECPrivateKeyFromPEM(opts.PrivateKey)
		if err != nil {
			return nil, err
		}
	}

	if len(opts.PublicKey) > 0 {
		pub, err = jwt.ParseECPublicKeyFromPEM(opts.PublicKey)
		if err != nil {
			return nil, err
		}
	}

	if priv == nil {
		if pub == nil {
			// Neither key given
			return nil, ErrMissingKey
		}
		// Public key only, can verify tokens
		return pub, nil
	}

	// both keys provided, make sure they match
	if pub != nil && pub.Curve != priv.Curve &&
		pub.X.Cmp(priv.X) != 0 && pub.Y.Cmp(priv.Y) != 0 {
		return nil, ErrKeyMismatch
	}

	return priv, nil
}
