// Copyright 2016 Google Inc. All Rights Reserved.
//
// 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 logadmin

import (
	"fmt"

	vkit "cloud.google.com/go/logging/apiv2"
	"golang.org/x/net/context"
	"google.golang.org/api/iterator"
	logpb "google.golang.org/genproto/googleapis/logging/v2"
)

// Metric describes a logs-based metric. The value of the metric is the
// number of log entries that match a logs filter.
//
// Metrics are a feature of Stackdriver Monitoring.
// See https://cloud.google.com/monitoring/api/v3/metrics for more about them.
type Metric struct {
	// ID is a client-assigned metric identifier. Example:
	// "severe_errors".  Metric identifiers are limited to 1000
	// characters and can include only the following characters: A-Z,
	// a-z, 0-9, and the special characters _-.,+!*',()%/\.  The
	// forward-slash character (/) denotes a hierarchy of name pieces,
	// and it cannot be the first character of the name.
	ID string

	// Description describes this metric. It is used in documentation.
	Description string

	// Filter is an advanced logs filter (see
	// https://cloud.google.com/logging/docs/view/advanced_filters).
	// Example: "logName:syslog AND severity>=ERROR".
	Filter string
}

// CreateMetric creates a logs-based metric.
func (c *Client) CreateMetric(ctx context.Context, m *Metric) error {
	_, err := c.mClient.CreateLogMetric(ctx, &logpb.CreateLogMetricRequest{
		Parent: c.parent(),
		Metric: toLogMetric(m),
	})
	return err
}

// DeleteMetric deletes a log-based metric.
// The provided metric ID is the metric identifier. For example, "severe_errors".
func (c *Client) DeleteMetric(ctx context.Context, metricID string) error {
	return c.mClient.DeleteLogMetric(ctx, &logpb.DeleteLogMetricRequest{
		MetricName: c.metricPath(metricID),
	})
}

// Metric gets a logs-based metric.
// The provided metric ID is the metric identifier. For example, "severe_errors".
// Requires ReadScope or AdminScope.
func (c *Client) Metric(ctx context.Context, metricID string) (*Metric, error) {
	lm, err := c.mClient.GetLogMetric(ctx, &logpb.GetLogMetricRequest{
		MetricName: c.metricPath(metricID),
	})
	if err != nil {
		return nil, err
	}
	return fromLogMetric(lm), nil
}

// UpdateMetric creates a logs-based metric if it does not exist, or updates an
// existing one.
func (c *Client) UpdateMetric(ctx context.Context, m *Metric) error {
	_, err := c.mClient.UpdateLogMetric(ctx, &logpb.UpdateLogMetricRequest{
		MetricName: c.metricPath(m.ID),
		Metric:     toLogMetric(m),
	})
	return err
}

func (c *Client) metricPath(metricID string) string {
	return fmt.Sprintf("%s/metrics/%s", c.parent(), metricID)
}

// Metrics returns a MetricIterator for iterating over all Metrics in the Client's project.
// Requires ReadScope or AdminScope.
func (c *Client) Metrics(ctx context.Context) *MetricIterator {
	it := &MetricIterator{
		it: c.mClient.ListLogMetrics(ctx, &logpb.ListLogMetricsRequest{Parent: c.parent()}),
	}
	it.pageInfo, it.nextFunc = iterator.NewPageInfo(
		it.fetch,
		func() int { return len(it.items) },
		func() interface{} { b := it.items; it.items = nil; return b })
	return it
}

// A MetricIterator iterates over Metrics.
type MetricIterator struct {
	it       *vkit.LogMetricIterator
	pageInfo *iterator.PageInfo
	nextFunc func() error
	items    []*Metric
}

// PageInfo supports pagination. See the google.golang.org/api/iterator package for details.
func (it *MetricIterator) PageInfo() *iterator.PageInfo { return it.pageInfo }

// Next returns the next result. Its second return value is Done if there are
// no more results. Once Next returns Done, all subsequent calls will return
// Done.
func (it *MetricIterator) Next() (*Metric, error) {
	if err := it.nextFunc(); err != nil {
		return nil, err
	}
	item := it.items[0]
	it.items = it.items[1:]
	return item, nil
}

func (it *MetricIterator) fetch(pageSize int, pageToken string) (string, error) {
	return iterFetch(pageSize, pageToken, it.it.PageInfo(), func() error {
		item, err := it.it.Next()
		if err != nil {
			return err
		}
		it.items = append(it.items, fromLogMetric(item))
		return nil
	})
}

func toLogMetric(m *Metric) *logpb.LogMetric {
	return &logpb.LogMetric{
		Name:        m.ID,
		Description: m.Description,
		Filter:      m.Filter,
	}
}

func fromLogMetric(lm *logpb.LogMetric) *Metric {
	return &Metric{
		ID:          lm.Name,
		Description: lm.Description,
		Filter:      lm.Filter,
	}
}
