// Copyright 2019 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 validator

import (
	"config"
	"fmt"
)

func CompareMetrics(oldMetric, newMetric *config.MetricDefinition, ignoreCompatChecks bool) error {
	// Debug metrics are ignored for the purposes of change validation.
	if oldMetric.MetaData != nil && oldMetric.MetaData.MaxReleaseStage <= config.ReleaseStage_DEBUG {
		return nil
	}

	if newMetric.MetaData != nil && newMetric.MetaData.MaxReleaseStage <= config.ReleaseStage_DEBUG {
		return nil
	}

	oldDimensions := map[int]*config.MetricDefinition_MetricDimension{}
	newDimensions := map[int]*config.MetricDefinition_MetricDimension{}

	for ix, dim := range oldMetric.MetricDimensions {
		oldDimensions[ix] = dim
	}

	for ix, dim := range newMetric.MetricDimensions {
		newDimensions[ix] = dim
	}

	for ix, oldDimension := range oldDimensions {
		newDimension, ok := newDimensions[ix]
		if ok {
			err := CompareDimensions(oldDimension, newDimension, ignoreCompatChecks)
			if err != nil {
				return fmt.Errorf("for dimension index '%d': %v", ix, err)
			}

			if oldMetric.MetricType == config.MetricDefinition_EVENT_OCCURRED || newMetric.MetricType == config.MetricDefinition_EVENT_OCCURRED {
				if oldDimension.MaxEventCode != newDimension.MaxEventCode && !ignoreCompatChecks {
					return fmt.Errorf("for dimension index '%d': changing max_event_code is not allowed for EVENT_OCCURRED metrics", ix)
				}
			}
		}
	}

	newReports := map[string]*config.ReportDefinition{}
	newReportIds := map[uint32]bool{}
	for _, report := range newMetric.Reports {
		newReports[report.ReportName] = report
		newReportIds[report.Id] = true
	}

	oldReports := map[string]*config.ReportDefinition{}
	newlyDeletedReportIds := map[uint32]string{}
	for _, report := range oldMetric.Reports {
		oldReports[report.ReportName] = report
		_, ok := newReportIds[report.Id]
		if !ok {
			newlyDeletedReportIds[report.Id] = report.ReportName
		}
	}

	for name, oldReport := range oldReports {
		newReport, ok := newReports[name]
		if ok {
			err := CompareReports(oldReport, newReport, ignoreCompatChecks)
			if err != nil {
				return fmt.Errorf("for report named '%s': %v", name, err)
			}
		}
	}

	for newlyDeletedReportId, newlyDeletedReportName := range newlyDeletedReportIds {
		found := false
		for _, deletedReportId := range newMetric.DeletedReportIds {
			if deletedReportId == newlyDeletedReportId {
				found = true
				break
			}
		}
		if !found && !ignoreCompatChecks {
			return fmt.Errorf("for report named '%s': the deleted report's ID %v must be added to the deleted_reports for the metric", newlyDeletedReportName, newlyDeletedReportId)
		}
	}

	return nil
}

func CompareDimensions(oldDimension, newDimension *config.MetricDefinition_MetricDimension, ignoreCompatChecks bool) error {
	for code, oldName := range oldDimension.EventCodes {
		_, ok := newDimension.EventCodes[code]
		if !ok && !ignoreCompatChecks {
			return fmt.Errorf("removing an event code is not allowed: %d: %s", code, oldName)
		}
	}

	return nil
}
