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

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"os"

	"github.com/apid/istioApigeeAdapter/adapter/config"
	me "github.com/hashicorp/go-multierror"
	"istio.io/mixer/pkg/adapter"
)

type (
	builder struct{ adapter.DefaultBuilder }

	logger struct{ logStream io.Writer }

	analyticsRecord struct {
		ClientReceivedStartTimestamp int    `json:"client_received_start_timestamp"`
		ClientReceivedEndTimestamp   int    `json:"client_received_end_timestamp"`
		RecordType                   string `json:"recordType"`
		ApiProxy                     string `json:"apiproxy"`
		RequestUri                   string `json:"request_uri"`
		RequestPath                  string `json:"request_path"`
		RequestVerb                  string `json:"request_verb"`
		ClientIp                     string `json:"client_ip"`
		UserAgent                    string `json:"useragent"`
		ApiProxyRevision             string `json:"apiproxy_revision"`
		ResponseStatusCode           int    `json:"response_status_code"`
		ClientSentStartTimestamp     int    `json:"client_sent_start_timestamp"`
		ClientSentEndTimestamp       int    `json:"client_sent_end_timestamp"`
		DeveloperEmail               string `json:"developer_email,omitempty"`
		DeveloperApp                 string `json:"developer_app"`
		AccessToken                  string `json:"access_token,omitempty"`
		ClientId                     string `json:"client_id,omitempty"`
		ApiProduct                   string `json:"api_product"`
	}

	analyticsRecordCollection struct {
		Records []analyticsRecord `json:"records"`
	}

	edgemicroKeys struct {
		Key    string
		Secret string
	}
)

func newReportBuilder() builder {
	return builder{adapter.NewDefaultBuilder(
		"apigeeReport",
		"Report logs to apigee",
		&config.ReportParams{},
	)}
}

func (builder) NewApplicationLogsAspect(env adapter.Env, cfg adapter.Config) (adapter.ApplicationLogsAspect, error) {
	return newLogger(cfg)
}

func (builder) NewAccessLogsAspect(env adapter.Env, cfg adapter.Config) (adapter.AccessLogsAspect, error) {
	return newLogger(cfg)
}

func newLogger(cfg adapter.Config) (*logger, error) {
	c := cfg.(*config.ReportParams)

	w := os.Stderr
	if c.LogStream == config.STDOUT {
		w = os.Stdout
	}

	return &logger{w}, nil
}

func (l *logger) Log(entries []adapter.LogEntry) error {
	return l.log(entries)
}

func (l *logger) LogAccess(entries []adapter.LogEntry) error {
	fmt.Println("*** here")
	return l.log(entries)
}

func (l *logger) log(entries []adapter.LogEntry) error {
	var recordsCollection []analyticsRecord

	var errors *me.Error
	for _, entry := range entries {

		if err := writeJSON(l.logStream, entry); err != nil {
			errors = me.Append(errors, err)
		}

		ax_data := analyticsRecord{
			ClientReceivedStartTimestamp: 33,
			DeveloperApp:                 "microgateway-demo",
		}

		recordsCollection = append(recordsCollection, ax_data)

	}

	res2B, _ := json.Marshal(recordsCollection)
	fmt.Println(string(res2B))

	return errors.ErrorOrNil()
}

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

func writeJSON(w io.Writer, le interface{}) error {
	return json.NewEncoder(w).Encode(le)
}

func sendAnalyticsRecords(collection analyticsRecordCollection, keys edgemicroKeys, uri string) bool {
	serializedBody, _ := json.Marshal(&collection)
	req, _ := http.NewRequest("POST", uri, bytes.NewBuffer(serializedBody))
	req.SetBasicAuth(keys.Key, keys.Secret)
	req.Header.Add("content-type", "application/json")
	client := &http.Client{}
	resp, _ := client.Do(req)
	if resp.StatusCode != 200 {
		return false
	} else {
		return true
	}
}
