/*
Copyright 2017 Google Inc.

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 adapter

import (
	"fmt"
	"strconv"
	"strings"
	"github.com/apid/istioApigeeAdapter/adapter/config"
	"istio.io/mixer/pkg/adapter"
)

const (
	keyAttrsName = "apigeeKeyAttributes"
	keyAttrsDesc = "Set attributes based on an Apigee API key"

	keyParam           = "apiKey"
	jwtParam	   = "jwtToken"
	pathParam          = "requestPath"
	successParam       = "success"
	successStringParam = "successString"
	clientIDParam      = "clientID"
	appNameParam       = "applicationName"
	productNameParam   = "apiProduct"
)

var keyAttrsConf = &config.VerifyKeyParams{}

type keyAttrsBuilder struct {
	adapter.DefaultBuilder
}

type keyAttrsGenerator struct {
	env          adapter.Env
	applications *applicationManager
	products     *productManager
	jwtVerifier  *jwtVerifier
}

func newKeyAttrsBuilder() adapter.AttributesGeneratorBuilder {
	return keyAttrsBuilder{
		adapter.NewDefaultBuilder(keyAttrsName, keyAttrsDesc, keyAttrsConf),
	}
}

func (b keyAttrsBuilder) ValidateConfig(c adapter.Config) *adapter.ConfigErrors {
	return validateKeyParams(c)
}

func (b keyAttrsBuilder) BuildAttributesGenerator(env adapter.Env, c adapter.Config) (adapter.AttributesGenerator, error) {
	cfg := c.(*config.VerifyKeyParams)
	verifyPath, productsPath := getPaths(cfg)
	publicKeyUrl := getPulicKeyUrl(cfg)

	g := &keyAttrsGenerator{
		env:          env,
		applications: newApplicationManager(env, defaultAppLifetime, verifyPath),
		products:     newProductManager(productsPath, defaultProductsFetch),
		jwtVerifier:  newVerifier(defaultKeyFetch, publicKeyUrl),
	}
	env.Logger().Infof("Created Apigee attributes generator to invoke \"%s\"", verifyPath)
	env.Logger().Infof("Checking API products using \"%s\"", productsPath)

	return g, nil
}

func (g *keyAttrsGenerator) Generate(in map[string]interface{}) (map[string]interface{}, error) {

	out := make(map[string]interface{})
	out[successParam] = false
	out[successStringParam] = "false"

	key := getString(in, keyParam)
	jwt_token := getString(in, jwtParam)

	if key == "" && jwt_token == "" {
		return out, nil
	}

	path := getString(in, pathParam)
	if path == "" {
		return out, nil
	}

	if jwt_token != "" {
		if strings.HasPrefix(jwt_token, "Bearer") {
			token := strings.Split(jwt_token, " ")[1]
			jwt_token = token
		} else {
			g.env.Logger().Errorf("Cannot verify jwt token, Bearer missing")
			return out, nil
		}

		claims, err := g.jwtVerifier.Verify(jwt_token)

		if err != nil {
			g.env.Logger().Errorf("Cannot verify jwt token : %s", err)
			return out, nil
		}

		// considers token as valid if exp, iat, iss is not present
		err = claims.Valid()

		// invalid token
		if err != nil {
			g.env.Logger().Errorf("jwt token invalid : %s", err)
			return out, nil
		}

		// TODO: check scopes

		// prioritizing jwt over apikey (if user passes both jwt and apikey)
		key = claims.(*apigeeClaims).ClientId
	}

	// Look up API key from cache, making HTTP request if necessary
	app, err := g.applications.get(key)
	if err != nil {
		g.env.Logger().Errorf("Error verifying API key: %s", err)
		return nil, err
	}

	success := app.valid

	// Look up API products from cache, making HTTP request if necessary
	products, err := g.products.getProducts(app.apiProducts)
	if err != nil {
		return nil, fmt.Errorf("Cannot fetch API product list: %s", err)
	}
	if len(products) == 0 {
		success = false
	}
	// TODO match API products by path

	out[successParam] = success
	out[successStringParam] = strconv.FormatBool(success)
	if app.valid {
		out[clientIDParam] = app.clientID
		out[appNameParam] = app.name
	}
	if success {
		out[productNameParam] = products[0].Name
	}

	return out, nil
}

func (g *keyAttrsGenerator) Close() error {
	return nil
}

func getPulicKeyUrl(cfg *config.VerifyKeyParams) (string) {
	return fmt.Sprintf(defaultPublicKeyURL, cfg.Organization, cfg.Environment)
}