// Watch on all alerts
func (kva *KvAlerts) Watch(alertsWatcherFunc AlertsWatcherFunc) error {

	prefix := alertsKey
	alertsWatcher = watcher{status: watchBootstrap, cb: alertsWatcherFunc, kvcb: kvdbWatch}

	if err := subscribeWatch(); err != nil {
		return err
	}

	// Subscribe for a watch is in a goroutine. Bootsrap by writing to the key and waiting for an update
	retries := 0
	kv := kvdb.Instance()
	for alertsWatcher.status == watchBootstrap {
		_, err := kv.Put(prefix+bootstrap, time.Now(), 1)
		if err != nil {
			return err
		}
		if alertsWatcher.status == watchBootstrap {
			retries++
			time.Sleep(time.Millisecond * 100)
		}
	}
	if alertsWatcher.status != watchReady {
		return fmt.Errorf("Failed to watch on %v", prefix)
	}

	return nil
}
func TestEnumerateAlerts(t *testing.T) {
	// RaiseWithGenerateId a few alerts
	raiseAlert1, err := kva.RaiseWithGenerateId(api.Alerts{Resource: api.ResourceType_VOLUMES, Severity: api.SeverityType_NOTIFY}, mockGenerateId)
	raiseAlert2, err := kva.RaiseWithGenerateId(api.Alerts{Resource: api.ResourceType_VOLUMES, Severity: api.SeverityType_NOTIFY}, mockGenerateId)
	raiseAlert3, err := kva.RaiseWithGenerateId(api.Alerts{Resource: api.ResourceType_VOLUMES, Severity: api.SeverityType_WARNING}, mockGenerateId)
	raiseAlert4, err := kva.RaiseWithGenerateId(api.Alerts{Resource: api.ResourceType_NODE, Severity: api.SeverityType_WARNING}, mockGenerateId)

	enAlerts, err := kva.Enumerate(api.Alerts{Resource: api.ResourceType_VOLUMES})
	require.NoError(t, err, "Failed to enumerate alerts")
	require.Equal(t, 3, len(enAlerts), "Enumerated incorrect number of alerts")

	enAlerts, err = kva.Enumerate(api.Alerts{Resource: api.ResourceType_VOLUMES, Severity: api.SeverityType_WARNING})
	require.NoError(t, err, "Failed to enumerate alerts")
	require.Equal(t, 1, len(enAlerts), "Enumerated incorrect number of alerts")
	require.Equal(t, api.SeverityType_WARNING, enAlerts[0].Severity, "Severity mismatch")

	enAlerts, err = kva.Enumerate(api.Alerts{})
	require.NoError(t, err, "Failed to enumerate alerts")
	require.Equal(t, 4, len(enAlerts), "Enumerated incorrect number of alerts")

	enAlerts, err = kva.Enumerate(api.Alerts{Severity: api.SeverityType_WARNING})
	require.NoError(t, err, "Failed to enumerate alerts")
	require.Equal(t, 2, len(enAlerts), "Enumerated incorrect number of alerts")
	require.Equal(t, api.SeverityType_WARNING, enAlerts[0].Severity, "Severity mismatch")

	// Add a dummy event into kvdb two hours ago
	kv := kvdb.Instance()
	currentTime := time.Now()
	delayedTime := currentTime.Add(-1 * time.Duration(2) * time.Hour)

	alert := api.Alerts{Timestamp: prototime.TimeToTimestamp(delayedTime), Id: 10, Resource: api.ResourceType_VOLUMES}

	_, err = kv.Put(getResourceKey(api.ResourceType_VOLUMES)+strconv.FormatInt(10, 10), &alert, 0)
	enAlerts, err = kva.EnumerateWithinTimeRange(currentTime.Add(-1*time.Duration(10)*time.Second), currentTime, api.ResourceType_VOLUMES)
	require.NoError(t, err, "Failed to enumerate results")
	require.Equal(t, 3, len(enAlerts), "Enumerated incorrect number of alerts")

	err = kva.Erase(api.ResourceType_VOLUMES, raiseAlert1.Id)
	err = kva.Erase(api.ResourceType_VOLUMES, raiseAlert2.Id)
	err = kva.Erase(api.ResourceType_VOLUMES, raiseAlert3.Id)
	err = kva.Erase(api.ResourceType_NODE, raiseAlert4.Id)
}