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

	"github.com/apid/istioApigeeAdapter/adapter/config"
	"istio.io/mixer/pkg/adapter"
)

const (
	checkName        = "apigeeKeyChecker"
	checkDesc        = "Verify an API key from a parameter"
	verifyKeyPath    = "/verifyApiKey"
	productsPath     = "/products"
	defaultVerifyURL = "https://%s-%s.apigee.net/edgemicro-auth"
)

var checkConf = &config.VerifyKeyParams{}

type keyCheckBuilder struct {
	adapter.DefaultBuilder
}

type keyChecker struct {
	env         adapter.Env
	application *applicationManager
}

func newKeyCheckBuilder() adapter.ListsBuilder {
	return keyCheckBuilder{
		adapter.NewDefaultBuilder(checkName, checkDesc, checkConf),
	}
}

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

func validateKeyParams(c adapter.Config) (ce *adapter.ConfigErrors) {
	cfg := c.(*config.VerifyKeyParams)
	if cfg.Organization == "" {
		ce = ce.Appendf("organization", "Organization parameter must be specified")
	}
	if cfg.Environment == "" {
		ce = ce.Appendf("environment", "Environment parameter must be specified")
	}
	if cfg.VerificationURL != "" {
		_, err := url.Parse(cfg.VerificationURL)
		if err != nil {
			ce = ce.Appendf("verificationURL", "Invalid verification URL: %s", err)
		}
	}
	return
}

func (b keyCheckBuilder) NewListsAspect(env adapter.Env, c adapter.Config) (adapter.ListsAspect, error) {
	cfg := c.(*config.VerifyKeyParams)
	verifyPath, _ := getPaths(cfg)
	kc := &keyChecker{
		env:         env,
		application: newApplicationManager(env, defaultAppLifetime, verifyPath),
	}
	env.Logger().Infof("Created Apigee Key Checker to invoke \"%s\"", kc.application.checkURL)

	return kc, nil
}

func getPaths(cfg *config.VerifyKeyParams) (string, string) {
	var basePath string

	if cfg.VerificationURL == "" {
		basePath = fmt.Sprintf(defaultVerifyURL, cfg.Organization, cfg.Environment)
	} else {
		basePath = cfg.VerificationURL
	}
	return basePath + verifyKeyPath, basePath + productsPath
}

func (l *keyChecker) Close() error {
	return nil
}

// CheckList is part of the interface for a "list checker" adapter. It's the part that
// gets whatever the value is (we want it to be the API key in our case) and checks it.

// Test command ./bazel-bin/cmd/client/mixc check -a target.service=f.default.svc.cluster.local --stringmap_attributes request.headers=x-api-key:1tu9pl04Srua2MtsAGtu6ViPxSYSSX2I

func (l *keyChecker) CheckList(symbol string) (bool, error) {
	app, err := l.application.get(symbol)
	if err != nil {
		l.env.Logger().Errorf("Error verifying API key: %s", err)
		return false, err
	}
	return app.valid, nil
}
