// 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 logadmin

import (
	"context"
	"fmt"

	vkit "cloud.google.com/go/logging/apiv2"
	"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 Cloud 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,
	}
}
