/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 registry

import (
	"fmt"
)

import (
	gxset "github.com/dubbogo/gost/container/set"
	gxpage "github.com/dubbogo/gost/page"
)

const DefaultPageSize = 100

// ServiceDiscovery is the common operations of Service Discovery
type ServiceDiscovery interface {
	fmt.Stringer

	// ----------------- lifecycle -------------------

	// Destroy will destroy the service discovery.
	// If the discovery cannot be destroy, it will return an error.
	Destroy() error

	// ----------------- registration ----------------

	// Register will register an instance of ServiceInstance to registry
	Register(instance ServiceInstance) error

	// Update will update the data of the instance in registry
	Update(instance ServiceInstance) error

	// Unregister will unregister this instance from registry
	Unregister(instance ServiceInstance) error

	// ----------------- discovery -------------------
	// GetDefaultPageSize will return the default page size
	GetDefaultPageSize() int

	// GetServices will return the all service names.
	GetServices() *gxset.HashSet

	// GetInstances will return all service instances with serviceName
	GetInstances(serviceName string) []ServiceInstance

	// GetInstancesByPage will return a page containing instances of ServiceInstance with the serviceName
	// the page will start at offset
	GetInstancesByPage(serviceName string, offset int, pageSize int) gxpage.Pager

	// GetHealthyInstancesByPage will return a page containing instances of ServiceInstance.
	// The param healthy indices that the instance should be healthy or not.
	// The page will start at offset
	GetHealthyInstancesByPage(serviceName string, offset int, pageSize int, healthy bool) gxpage.Pager

	// Batch get all instances by the specified service names
	GetRequestInstances(serviceNames []string, offset int, requestedSize int) map[string]gxpage.Pager

	// ----------------- event ----------------------
	// AddListener adds a new ServiceInstancesChangedListener
	// see addServiceInstancesChangedListener in Java
	AddListener(listener *ServiceInstancesChangedListener) error

	// DispatchEventByServiceName dispatches the ServiceInstancesChangedEvent to service instance whose name is serviceName
	DispatchEventByServiceName(serviceName string) error

	// DispatchEventForInstances dispatches the ServiceInstancesChangedEvent to target instances
	DispatchEventForInstances(serviceName string, instances []ServiceInstance) error

	// DispatchEvent dispatches the event
	DispatchEvent(event *ServiceInstancesChangedEvent) error
}
