/*
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 (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
	"net/url"

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

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

var checkConf = &config.VerifyKeyParams{}

type keyCheckBuilder struct {
	adapter.DefaultBuilder
}

type keyChecker struct {
	env      adapter.Env
	checkURL string
}

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

func (b keyCheckBuilder) ValidateConfig(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)
	var basePath string

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

	kc := &keyChecker{
		env:      env,
		checkURL: basePath + verifyKeyPath,
	}
	env.Logger().Infof("Created Apigee Key Checker to invoke \"%s\"", kc.checkURL)

	return kc, nil
}

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) {
	apiKeyBody := common.VerifyAPIKeyRequest{
		Key: symbol,
	}
	requestBody, _ := json.Marshal(&apiKeyBody)

	resp, err := http.DefaultClient.Post(l.checkURL, "application/json",
		bytes.NewBuffer(requestBody))
	if err != nil {
		l.env.Logger().Errorf("Error contacting verification service: %s", err)
		return false, err
	}
	defer resp.Body.Close()

	if resp.StatusCode != 200 {
		return false, nil
	} else {
		return true, nil
	}
}
