// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package config_validator

import (
	"config"
	"fmt"
	"github.com/golang/glog"
	"regexp"
	"time"
)

// Note that when reports are serialized to CSV, the column headers used are
// derived from metric part names. Consequently, if this regular expression
// is modified then the code in the function
// EscapeMetricPartNameForCSVColumHeader() in
// //analyzer/report_master/report_serializer.cc must be modified.
var validMetricPartName = regexp.MustCompile("^[a-zA-Z][_a-zA-Z0-9\\- ]+$")

func validateConfiguredMetrics(config *config.CobaltConfig) (err error) {
	// Set of encodingIds. Used to check that the Metric only refers to valid encodingIds.
	encodingIds := map[string]bool{}

	// Set of metric ids. Used to detect duplicates.
	metricIds := map[string]bool{}

	for _, encoding := range config.EncodingConfigs {
		encodingIds[formatId(encoding.CustomerId, encoding.ProjectId, encoding.Id)] = true
	}

	for i, metric := range config.MetricConfigs {
		metricKey := formatId(metric.CustomerId, metric.ProjectId, metric.Id)

		if metricIds[metricKey] {
			return fmt.Errorf("Metric id %s is repeated in metric config entry number %v. Metric ids must be unique.", metricKey, i+1)
		}
		metricIds[metricKey] = true

		if err = validateMetric(metric, encodingIds); err != nil {
			return fmt.Errorf("Error validating metric %v (%v, %v, %v): %v", metric.Name, metric.CustomerId, metric.ProjectId, metric.Id, err)
		}
	}
	return nil
}

func validateMetric(m *config.Metric, encodingIds map[string]bool) (err error) {
	if m.Id == 0 {
		return fmt.Errorf("Metric id '0' is invalid.")
	}

	if m.ProjectId >= 100 {
		if m.GetMetaData() == nil || m.GetMetaData().ExpiresAfter == "" {
			return fmt.Errorf("expires_after is not present. All metrics with project_id > 100 must have an expires_after field set.")
		}

		oldestValidExpiry := time.Now().AddDate(1, 0, 0)
		date, err := time.Parse("2006/01/02", m.GetMetaData().ExpiresAfter)
		if err != nil {
			return fmt.Errorf("Unable to parse expires_after. Format should be yyyy/mm/dd. %v", err)
		}

		if date.After(oldestValidExpiry) {
			return fmt.Errorf("Expiry date '%v' is past the maximum expiry date of '%v'", date, oldestValidExpiry)
		}

		// We don't currently enforce expiry dates in code, but we should warn about it.
		if date.Before(time.Now()) {
			glog.Warningf("Metric '%v' (Customer %v, Project %v, Id %v) has expired.", m.Name, m.CustomerId, m.ProjectId, m.Id)
		} else if date.Before(time.Now().AddDate(0, 3, 0)) {
			glog.Warningf("Metric '%v' (Customer %v, Project %v, Id %v) will expire within 3 months.", m.Name, m.CustomerId, m.ProjectId, m.Id)
		}
	}

	for name, v := range m.Parts {
		if v == nil {
			return fmt.Errorf("Metric part '%v' is null. This is not allowed.", name)
		}

		if !validMetricPartName.MatchString(name) {
			return fmt.Errorf("Metric part name '%v' is invalid. Metric part names must match the regular expression '%v'.", name, validMetricPartName)
		}

		encodingId := formatId(m.CustomerId, m.ProjectId, v.DefaultEncodingId)
		if !encodingIds[encodingId] {
			return fmt.Errorf("Metric part '%v' is invalid. There is no encoding id %v.", name, encodingId)
		}
	}
	return nil
}
