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

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("https://%s-%s.apigee.net/edgemicro-auth",
			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
	}
}
