/*
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"
	"github.com/apid/istioApigeeAdapter/common"
)

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

	keyParam           	 = "apiKey"
	jwtParam	   	 = "jwtToken"
	pathParam          	 = "requestPath"
	apiKeySuccessParam       = "apiKeySuccess"
	apiKeySuccessStringParam = "apiKeySuccessString"
	jwtSuccessParam       	 = "jwtSuccess"
	jwtSuccessStringParam 	 = "jwtSuccessString"
	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[apiKeySuccessParam] = false
	out[apiKeySuccessStringParam] = "false"
	out[jwtSuccessParam] = false
	out[jwtSuccessStringParam] = "false"

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

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

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

	if jwt_token != "" {
		// TODO: throw appropriate error to user eg. token expired, token invalid

		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")
		}

		claims, verificationErr := g.jwtVerifier.Verify(jwt_token)
		// considers token as valid if exp, iat, iss is not present

		if verificationErr != nil {
			g.env.Logger().Errorf("Cannot verify jwt token : %s", verificationErr)
		} else {
			validationErr := claims.Valid()

			if validationErr != nil {
				g.env.Logger().Errorf("Validation error, jwt token : %s", validationErr)
			} else {
				// TODO: check scopes

				key := claims.(*apigeeClaims).ClientId
				success, app, products, err := g.checkKey(key)

				g.env.Logger().Errorf("Key check failed : %s", err)

				out[jwtSuccessParam] = success
				out[jwtSuccessStringParam] = strconv.FormatBool(success)

				if app.valid {
					out[clientIDParam] = app.clientID
					out[appNameParam] = app.name
				}

				if success {
					out[productNameParam] = products[0].Name
				}
			}
		}
	}

	if apiKey != "" {
		success, app, products, err := g.checkKey(apiKey)

		g.env.Logger().Errorf("key check failed : %s", err)

		if len(products) == 0 {
			success = false
		}

		// TODO match API products by path

		out[apiKeySuccessParam] = success
		out[apiKeySuccessStringParam] = 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 (g *keyAttrsGenerator) checkKey(key string) (bool, *application, []common.APIProduct, error) {
	// 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 false, nil, 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 false, nil, nil, fmt.Errorf("Cannot fetch API product list: %s", err)
	}

	if len(products) == 0 {
		success = false
	}

	// TODO match API products by path

	return success, app, products, err
}

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