// Copyright 2016 Google LLC
//
// 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 errorreporting is a Google Stackdriver Error Reporting library.
//
// This package is still experimental and subject to change.
//
// See https://cloud.google.com/error-reporting/ for more information.
package errorreporting // import "cloud.google.com/go/errorreporting"

import (
	"bytes"
	"fmt"
	"log"
	"net/http"
	"runtime"
	"time"

	vkit "cloud.google.com/go/errorreporting/apiv1beta1"
	"cloud.google.com/go/internal/version"
	"github.com/golang/protobuf/ptypes"
	gax "github.com/googleapis/gax-go"
	"golang.org/x/net/context"
	"google.golang.org/api/option"
	"google.golang.org/api/support/bundler"
	pb "google.golang.org/genproto/googleapis/devtools/clouderrorreporting/v1beta1"
)

const (
	userAgent = `gcloud-golang-errorreporting/20160701`
)

// Config is additional configuration for Client.
type Config struct {
	// ServiceName identifies the running program and is included in the error reports.
	// Optional.
	ServiceName string

	// ServiceVersion identifies the version of the running program and is
	// included in the error reports.
	// Optional.
	ServiceVersion string

	// OnError is the function to call if any background
	// tasks errored. By default, errors are logged.
	OnError func(err error)
}

// Entry holds information about the reported error.
type Entry struct {
	Error error
	Req   *http.Request // if error is associated with a request.
	User  string        // an identifier for the user affected by the error
	Stack []byte        // if user does not provide a stack trace, runtime.Stack will be called
}

// Client represents a Google Cloud Error Reporting client.
type Client struct {
	projectName    string
	apiClient      client
	serviceContext *pb.ServiceContext
	bundler        *bundler.Bundler

	onErrorFn func(err error)
}

var newClient = func(ctx context.Context, opts ...option.ClientOption) (client, error) {
	client, err := vkit.NewReportErrorsClient(ctx, opts...)
	if err != nil {
		return nil, err
	}
	client.SetGoogleClientInfo("gccl", version.Repo)
	return client, nil
}

// NewClient returns a new error reporting client. Generally you will want
// to create a client on program initialization and use it through the lifetime
// of the process.
func NewClient(ctx context.Context, projectID string, cfg Config, opts ...option.ClientOption) (*Client, error) {
	if cfg.ServiceName == "" {
		cfg.ServiceName = "goapp"
	}
	c, err := newClient(ctx, opts...)
	if err != nil {
		return nil, fmt.Errorf("creating client: %v", err)
	}

	client := &Client{
		apiClient:   c,
		projectName: "projects/" + projectID,
		serviceContext: &pb.ServiceContext{
			Service: cfg.ServiceName,
			Version: cfg.ServiceVersion,
		},
		onErrorFn: cfg.OnError,
	}
	bundler := bundler.NewBundler((*pb.ReportErrorEventRequest)(nil), func(bundle interface{}) {
		reqs := bundle.([]*pb.ReportErrorEventRequest)
		for _, req := range reqs {
			_, err = client.apiClient.ReportErrorEvent(ctx, req)
			if err != nil {
				client.onError(err)
			}
		}
	})
	// TODO(jbd): Optimize bundler limits.
	bundler.DelayThreshold = 2 * time.Second
	bundler.BundleCountThreshold = 100
	bundler.BundleByteThreshold = 1000
	bundler.BundleByteLimit = 1000
	bundler.BufferedByteLimit = 10000
	client.bundler = bundler
	return client, nil
}

func (c *Client) onError(err error) {
	if c.onErrorFn != nil {
		c.onErrorFn(err)
		return
	}
	log.Println(err)
}

// Close calls Flush, then closes any resources held by the client.
// Close should be called when the client is no longer needed.
func (c *Client) Close() error {
	c.Flush()
	return c.apiClient.Close()
}

// Report writes an error report. It doesn't block. Errors in
// writing the error report can be handled via Config.OnError.
func (c *Client) Report(e Entry) {
	c.bundler.Add(c.newRequest(e), 1)
}

// ReportSync writes an error report. It blocks until the entry is written.
func (c *Client) ReportSync(ctx context.Context, e Entry) error {
	_, err := c.apiClient.ReportErrorEvent(ctx, c.newRequest(e))
	return err
}

// Flush blocks until all currently buffered error reports are sent.
//
// If any errors occurred since the last call to Flush, or the
// creation of the client if this is the first call, then Flush reports the
// error via the Config.OnError handler.
func (c *Client) Flush() {
	c.bundler.Flush()
}

func (c *Client) newRequest(e Entry) *pb.ReportErrorEventRequest {
	var stack string
	if e.Stack != nil {
		stack = string(e.Stack)
	} else {
		// limit the stack trace to 16k.
		var buf [16 * 1024]byte
		stack = chopStack(buf[0:runtime.Stack(buf[:], false)])
	}
	message := e.Error.Error() + "\n" + stack

	var errorContext *pb.ErrorContext
	if r := e.Req; r != nil {
		errorContext = &pb.ErrorContext{
			HttpRequest: &pb.HttpRequestContext{
				Method:    r.Method,
				Url:       r.Host + r.RequestURI,
				UserAgent: r.UserAgent(),
				Referrer:  r.Referer(),
				RemoteIp:  r.RemoteAddr,
			},
		}
	}
	if e.User != "" {
		if errorContext == nil {
			errorContext = &pb.ErrorContext{}
		}
		errorContext.User = e.User
	}
	return &pb.ReportErrorEventRequest{
		ProjectName: c.projectName,
		Event: &pb.ReportedErrorEvent{
			EventTime:      ptypes.TimestampNow(),
			ServiceContext: c.serviceContext,
			Message:        message,
			Context:        errorContext,
		},
	}
}

// chopStack trims a stack trace so that the function which panics or calls
// Report is first.
func chopStack(s []byte) string {
	f := []byte("cloud.google.com/go/errorreporting.(*Client).Report")

	lfFirst := bytes.IndexByte(s, '\n')
	if lfFirst == -1 {
		return string(s)
	}
	stack := s[lfFirst:]
	panicLine := bytes.Index(stack, f)
	if panicLine == -1 {
		return string(s)
	}
	stack = stack[panicLine+1:]
	for i := 0; i < 2; i++ {
		nextLine := bytes.IndexByte(stack, '\n')
		if nextLine == -1 {
			return string(s)
		}
		stack = stack[nextLine+1:]
	}
	return string(s[:lfFirst+1]) + string(stack)
}

type client interface {
	ReportErrorEvent(ctx context.Context, req *pb.ReportErrorEventRequest, opts ...gax.CallOption) (*pb.ReportErrorEventResponse, error)
	Close() error
}
