// 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"
	"config_parser"
	"fmt"
	"net/mail"
	"regexp"
	"strings"
	"time"

	"github.com/golang/protobuf/proto"
)

// This file contains logic to validate lists of MetricDefinition protos.

// Date format is yyyy/mm/dd. This is done by specifying in the desired format
// Mon Jan 2 15:04:05 MST 2006. See time module documentation.
const dateFormat = "2006/01/02"

// Valid names are 1-64 characters long. They have the same syntactic requirements
// as a C variable name.
var validNameRegexp = regexp.MustCompile("^[a-zA-Z][_a-zA-Z0-9]{1,65}$")

// Valid proto names are 1-64 characters long. They have the same syntactic
// requirements as a C variable name with the exceptions that they can include
// '.' for package names and '$' for '$team_name'.
var validProtoNameRegexp = regexp.MustCompile("^[$a-zA-Z][_.$a-zA-Z0-9]{1,64}[a-zA-Z0-9]$")

// Validate a list of MetricDefinitions.
func validateConfiguredMetricDefinitions(metrics []*config.MetricDefinition) (err error) {
	metricErrors := newValidationErrors("metric")

	metricIds := map[uint32]int{}
	metricNames := map[string]bool{}
	metricLookup := map[uint32]*config.MetricDefinition{}
	for i, metric := range metrics {
		if _, ok := metricIds[metric.Id]; ok {
			metricErrors.addError(fmt.Sprintf("Metric %d", metric.Id), fmt.Errorf("there are two metrics with id=%v", metric.Id))
			continue
		}
		metricIds[metric.Id] = i

		if _, ok := metricNames[metric.MetricName]; ok {
			metricErrors.addError(metric.MetricName, fmt.Errorf("there are two metrics with name=%v", metric.MetricName))
			continue
		}
		metricNames[metric.MetricName] = true

		metricLookup[metric.Id] = metric

		if err = validateMetricDefinition(*metric); err != nil {
			metricErrors.addError(metric.MetricName, err)
		}

	}

	replacementIds := map[uint32]string{}
	for _, metric := range metrics {
		if metric.ReplacementMetricId != 0 {
			if s, ok := replacementIds[metric.ReplacementMetricId]; ok {
				metricErrors.addError(metric.MetricName, fmt.Errorf("found metric with duplicate replacement_metric_id %s", s))
			}
			replacementIds[metric.ReplacementMetricId] = metric.MetricName
		}
		if err = validateReplacementMetricID(*metric, metricLookup); err != nil {
			metricErrors.addError(metric.MetricName, err)
		}
	}

	return metricErrors.err()
}

// Validate a single MetricDefinition.
func validateMetricDefinition(m config.MetricDefinition) (err error) {
	validationErrors := newValidationErrors("field")
	if !validNameRegexp.MatchString(m.MetricName) {
		validationErrors.addError("metric_name", fmt.Errorf("metric names must match the regular expression '%v'", validNameRegexp))
	}

	if m.Id == 0 {
		validationErrors.addError("id", fmt.Errorf("metric ID of zero is not allowed. Please specify a positive metric ID"))
	}

	if m.MetricType == config.MetricDefinition_UNSET {
		validationErrors.addError("metric_type", fmt.Errorf("is not set"))
	}

	if m.MetaData == nil {
		validationErrors.addError("meta_data", fmt.Errorf("meta_data is not set, additionally, in meta_data: %v", validateMetadata(config.MetricDefinition_Metadata{})))
	} else if err := validateMetadata(*m.MetaData); err != nil {
		validationErrors.addError("meta_data", err)
	}

	if err := validateMetricUnits(m); err != nil {
		validationErrors.addError("metric_units", err)
	}

	if m.IntBuckets != nil && m.MetricType != config.MetricDefinition_INT_HISTOGRAM && m.MetricType != config.MetricDefinition_INTEGER_HISTOGRAM {
		validationErrors.addError("int_buckets", fmt.Errorf("int_buckets can only be set for metrics for metric type INT_HISTOGRAM and INTEGER_HISTOGRAM"))
	}

	if m.ProtoName != "" && m.MetricType != config.MetricDefinition_CUSTOM {
		validationErrors.addError("proto_name", fmt.Errorf("proto_name can only be set for metrics for metric type CUSTOM"))
	}

	if config_parser.Cobalt11MetricTypesSet[m.MetricType] {
		if m.MetricSemantics == nil || len(m.MetricSemantics) == 0 {
			validationErrors.addError("metric_semantics", fmt.Errorf("metric_semantics is required for this metric"))
		}
	} else {
		if len(m.MetricSemantics) > 0 {
			validationErrors.addError("metric_semantics", fmt.Errorf("metric_semantics can only be set for Cobalt 1.1 metrics"))
		}
	}

	if err := validateMetricDefinitionForType(m); err != nil {
		validationErrors.addError("other", err)
	}

	if m.MetricType != config.MetricDefinition_CUSTOM {
		if err := validateMetricDimensions(m); err != nil {
			validationErrors.addError("metric_dimensions", err)
		}
	}

	err = validationErrors.err()
	if err != nil {
		return err
	}

	return validateReportDefinitions(m)
}

func validateReplacementMetricID(m config.MetricDefinition, mapping map[uint32]*config.MetricDefinition) (err error) {
	if m.ReplacementMetricId == 0 {
		return nil
	}

	if m.NoReplacementMetric != "" {
		return fmt.Errorf("replacement_metric_id and no_replacement_metric cannot be set at the same time")
	}

	replacement, ok := mapping[m.ReplacementMetricId]
	if !ok {
		return fmt.Errorf("replacement_metric_id must refer to an extant metric (metric %v doesn't exist)", m.ReplacementMetricId)
	}

	if len(m.MetricDimensions) != len(replacement.MetricDimensions) {
		return fmt.Errorf("replacement metric should have the same number of metric_dimensions (%d vs %d)", len(m.MetricDimensions), len(replacement.MetricDimensions))
	}
	for i := range m.MetricDimensions {
		if !proto.Equal(m.MetricDimensions[i], replacement.MetricDimensions[i]) {
			return fmt.Errorf("replacement metric does not contain the same metric_dimensions (%v != %v)", m.MetricDimensions[i].Dimension, replacement.MetricDimensions[i].Dimension)
		}
	}

	switch m.MetricType {
	case config.MetricDefinition_EVENT_OCCURRED, config.MetricDefinition_EVENT_COUNT:
		if replacement.MetricType != config.MetricDefinition_OCCURRENCE && replacement.MetricType != config.MetricDefinition_STRING && replacement.MetricType != config.MetricDefinition_INTEGER {
			return fmt.Errorf("metric of type %v must be mapped to one of (OCCURRENCE, STRING, INTEGER) event (found %v)", m.MetricType, replacement.MetricType)
		}
		if replacement.MetricType == config.MetricDefinition_OCCURRENCE || replacement.MetricType == config.MetricDefinition_INTEGER {
			for _, report := range m.Reports {
				if len(report.CandidateList) != 0 || len(report.CandidateFile) != 0 {
					return fmt.Errorf("metrics mapped to OCCURRENCE must contain no candidate based reports (found %v) with candidate_list or candidate_file set", report.Id)
				}
			}
		}
		if replacement.MetricType == config.MetricDefinition_STRING {
			for _, report := range m.Reports {
				if len(report.CandidateList) == 0 && len(report.CandidateFile) == 0 {
					return fmt.Errorf("report `%v`: metrics mapped to STRING must contain either candidate_list or candidate_file in all reports", report.Id)
				}
			}
		}
	case config.MetricDefinition_INT_HISTOGRAM:
		if replacement.MetricType != config.MetricDefinition_INTEGER_HISTOGRAM {
			return fmt.Errorf("metric of type INT_HISTOGRAM must be mapped to a metric of type INTEGER_HISTOGRAM (found %v)", replacement.MetricType)
		}
		for _, report := range m.Reports {
			if len(report.CandidateList) != 0 || len(report.CandidateFile) != 0 {
				return fmt.Errorf("metrics mapped to INTEGER_HISTOGRAM do not support candidate strings. Report %v contains one", report.Id)
			}
		}

		if m.IntBuckets != nil {
			if !proto.Equal(m.IntBuckets, replacement.IntBuckets) {
				return fmt.Errorf("replacement metric does not contain the same IntegerBuckets declaration")
			}
		}
	case config.MetricDefinition_FRAME_RATE, config.MetricDefinition_MEMORY_USAGE, config.MetricDefinition_ELAPSED_TIME:
		if replacement.MetricType != config.MetricDefinition_INTEGER {
			return fmt.Errorf("metric of type %v must be mapped to a metric of type INTEGER (found %v)", m.MetricType, replacement.MetricType)
		}
		for _, report := range m.Reports {
			if len(report.CandidateList) != 0 || len(report.CandidateFile) != 0 {
				return fmt.Errorf("metrics mapped to INTEGER do not support candidate strings. Report %v contains one", report.Id)
			}
		}
	case config.MetricDefinition_OCCURRENCE, config.MetricDefinition_INTEGER, config.MetricDefinition_INTEGER_HISTOGRAM, config.MetricDefinition_STRING:
		return fmt.Errorf("cobalt 1.1 metrics should not contain a replacement_metric_id field")
	case config.MetricDefinition_CUSTOM:
		return fmt.Errorf("CUSTOM metrics do not support replacement_metric_id")
	}
	return nil
}

// Validate a single instance of Metadata.
func validateMetadata(m config.MetricDefinition_Metadata) (err error) {
	errors := []string{}

	if len(m.ExpirationDate) == 0 {
		errors = append(errors, "expiration_date field is required")
	} else {
		var exp time.Time
		exp, err = time.ParseInLocation(dateFormat, m.ExpirationDate, time.UTC)
		if err != nil {
			errors = append(errors, fmt.Sprintf("expiration_date (%v) field is invalid, it must use the yyyy/mm/dd format", m.ExpirationDate))
		} else {
			// Date one year and one day from today.
			maxExp := time.Now().AddDate(1, 0, 0)
			if exp.After(maxExp) {
				errors = append(errors, fmt.Sprintf("expiration_date must be no later than %v", maxExp.Format(dateFormat)))
			}
		}
	}

	for _, o := range m.Owner {
		if _, err = mail.ParseAddress(o); err != nil {
			errors = append(errors, fmt.Sprintf("'%v' is not a valid email address in owner field", o))
		}
	}

	if m.MaxReleaseStage == config.ReleaseStage_RELEASE_STAGE_NOT_SET {
		errors = append(errors, "max_release_stage is required")
	}

	if len(errors) > 0 {
		return fmt.Errorf("%v", strings.Join(errors, ", "))
	} else {
		return nil
	}
}

// Validate the event_codes and max_event_code fields. Do not invoke on CUSTOM metrics.
func validateMetricDimensions(m config.MetricDefinition) error {
	if len(m.MetricDimensions) == 0 {
		// A metric definition is allowed to not have any metric dimensions.
		return nil
	}

	cobalt10MetricType := !(config_parser.Cobalt11MetricTypesSet[m.MetricType])

	if len(m.MetricDimensions) > 5 {
		return fmt.Errorf("there can be at most 5 dimensions in metric_dimensions")
	}

	seenNames := make(map[string]bool)
	numOptions := 1
	for i, md := range m.MetricDimensions {
		if md.Dimension == "" {
			return fmt.Errorf("dimension %d has no 'dimension' name", i)
		}

		if seenNames[md.Dimension] {
			return fmt.Errorf("duplicate dimension name in metric_dimensions %s", md.Dimension)
		}
		seenNames[md.Dimension] = true

		name := md.Dimension

		seenCodeNames := make(map[string]bool)
		for _, codeName := range md.EventCodes {
			if seenCodeNames[codeName] {
				return fmt.Errorf("duplicate event_code name in metric_dimensions %s", name)
			}
			seenCodeNames[codeName] = true
		}

		for from, to := range md.EventCodeAliases {
			if !seenCodeNames[from] {
				if seenCodeNames[to] {
					return fmt.Errorf("unknown event_code %s for alias %s: %s. Did you mean %s: %s?", from, from, to, to, from)
				} else {
					return fmt.Errorf("unknown event_code_alias: %s: %s", from, to)
				}
			}
			if seenCodeNames[to] {
				return fmt.Errorf("cannot have event_code_alias %s, when that name already exists in event_codes", to)
			}
		}

		if len(md.EventCodes) == 0 && md.MaxEventCode == 0 {
			return fmt.Errorf("for metric dimension %v, you must either define max_event_code or explicitly define at least one event code", name)
		}
		if md.MaxEventCode != 0 {
			for j := range md.EventCodes {
				if j > md.MaxEventCode {
					return fmt.Errorf("event index %v in metric_dimension %v is greater than max_event_code %v", j, name, md.MaxEventCode)
				}
			}
			numOptions *= int(md.MaxEventCode + 1)
		} else {
			for j := range md.EventCodes {
				if cobalt10MetricType && j >= 1024 && len(m.MetricDimensions) > 4 {
					return fmt.Errorf("event index %v in metric_dimension %v is greater than 1023, which means that this metric cannot support more than 4 metric_dimensions", j, name)
				}
				if j >= 32768 {
					return fmt.Errorf("event index %v in metric_dimension %v is is too large (greater than 32,767)", j, name)
				}
			}
			numOptions *= len(md.EventCodes)
		}
	}
	if cobalt10MetricType && numOptions >= 1024 {
		return fmt.Errorf("metric_dimensions have too many possible representations: %v. May be no more than 1023", numOptions)
	}

	return nil
}

func validateMetricUnits(m config.MetricDefinition) error {
	hasMetricUnits := m.MetricUnits != config.MetricUnits_METRIC_UNITS_OTHER
	hasMetricUnitsOther := len(m.MetricUnitsOther) > 0
	if m.MetricType != config.MetricDefinition_INTEGER && m.MetricType != config.MetricDefinition_INTEGER_HISTOGRAM {
		if hasMetricUnits || hasMetricUnitsOther {
			return fmt.Errorf("metric_units and metric_units_other must be set only for INTEGER and INTEGER_HISTOGRAM metrics")
		}
		return nil
	}

	if hasMetricUnits == hasMetricUnitsOther {
		return fmt.Errorf("metrics of type INTEGER and INTEGER_HISTOGRAM must have exactly one of metric_units or metric_units_other specified")
	}
	return nil
}

///////////////////////////////////////////////////////////////
// Validation for specific metric types:
///////////////////////////////////////////////////////////////

func validateMetricDefinitionForType(m config.MetricDefinition) error {
	switch m.MetricType {
	case config.MetricDefinition_EVENT_OCCURRED:
		return validateEventOccurred(m)
	case config.MetricDefinition_INT_HISTOGRAM:
		return validateIntHistogram(m)
	case config.MetricDefinition_EVENT_COUNT:
		return nil
	case config.MetricDefinition_FRAME_RATE:
		return nil
	case config.MetricDefinition_MEMORY_USAGE:
		return nil
	case config.MetricDefinition_ELAPSED_TIME:
		return nil
	case config.MetricDefinition_CUSTOM:
		return validateCustom(m)
	case config.MetricDefinition_OCCURRENCE:
		return nil
	case config.MetricDefinition_INTEGER:
		return nil
	case config.MetricDefinition_INTEGER_HISTOGRAM:
		return validateIntHistogram(m)
	case config.MetricDefinition_STRING:
		return validateString(m)
	}

	return fmt.Errorf("Unknown MetricType: %v", m.MetricType)
}

func validateEventOccurred(m config.MetricDefinition) error {
	if len(m.MetricDimensions) == 0 || m.MetricDimensions[0].MaxEventCode == 0 {
		return fmt.Errorf("no max_event_code specified for metric of type EVENT_OCCURRED")
	}

	if len(m.MetricDimensions) > 1 {
		return fmt.Errorf("too many metric dimensions specified for metric of type EVENT_OCCURRED")
	}

	for i, md := range m.MetricDimensions {
		if md.MaxEventCode == 0 {
			return fmt.Errorf("no max_event_code specified for metric_dimension %v", i)
		}
	}

	return nil
}

func validateIntHistogram(m config.MetricDefinition) error {
	if m.IntBuckets == nil {
		return fmt.Errorf("no int_buckets specified for metric of type INT_HISTOGRAM")
	}

	// TODO(azani): Validate bucket definition.

	for _, r := range m.Reports {
		if m.IntBuckets != nil && r.IntBuckets != nil {
			return fmt.Errorf("for report %q: both report and metric contain int_buckets stanzas, the stanza in %q will be ignored", r.ReportName, r.ReportName)
		}
	}

	return nil
}

func validateString(m config.MetricDefinition) error {
	if m.StringCandidateFile == "" {
		return fmt.Errorf("no string_candidate_file specified for metric of type STRING")
	}
	if m.StringBufferMax == 0 {
		return fmt.Errorf("no string_buffer_max specified for metric of type STRING")
	}

	return nil
}

func validateCustom(m config.MetricDefinition) error {
	if len(m.MetricDimensions) > 0 {
		return fmt.Errorf("metric_dimensions must not be set for metrics of type CUSTOM")
	}

	if m.ProtoName == "" {
		return fmt.Errorf("missing proto_name. Proto names are required for metrics of type CUSTOM")
	}

	if !validProtoNameRegexp.MatchString(m.ProtoName) {
		return fmt.Errorf("Invalid proto_name. Proto names must match the regular expression '%v'", validProtoNameRegexp)
	}

	return nil
}
