/*
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"

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

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)
	g := &keyAttrsGenerator{
		env:          env,
		applications: newApplicationManager(env, defaultAppLifetime, verifyPath),
		products:     newProductManager(productsPath, defaultProductsFetch),
	}
	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)
	if key == "" {
		return out, nil
	}
	path := getString(in, pathParam)
	if path == "" {
		return out, nil
	}

	// 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
}
