/*
 * 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 event

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

import (
	"github.com/apache/dubbo-go/common/extension"
	"github.com/apache/dubbo-go/common/observer"
	"github.com/apache/dubbo-go/config"
	"github.com/apache/dubbo-go/metadata/service"
	"github.com/apache/dubbo-go/registry"
)

// EventPublishingServiceDiscovery will enhance Service Discovery
// Publish some event about service discovery
type EventPublishingServiceDiscovery struct {
	serviceDiscovery registry.ServiceDiscovery
}

// NewEventPublishingServiceDiscovery is a constructor
func NewEventPublishingServiceDiscovery(serviceDiscovery registry.ServiceDiscovery) *EventPublishingServiceDiscovery {
	return &EventPublishingServiceDiscovery{
		serviceDiscovery: serviceDiscovery,
	}
}

// String returns serviceDiscovery.String()
func (epsd *EventPublishingServiceDiscovery) String() string {
	return epsd.serviceDiscovery.String()
}

// Destroy delegate function
func (epsd *EventPublishingServiceDiscovery) Destroy() error {
	f := func() error {
		return epsd.serviceDiscovery.Destroy()
	}
	return epsd.executeWithEvents(NewServiceDiscoveryDestroyingEvent(epsd, epsd.serviceDiscovery),
		f, NewServiceDiscoveryDestroyedEvent(epsd, epsd.serviceDiscovery))
}

// Register delegate function
func (epsd *EventPublishingServiceDiscovery) Register(instance registry.ServiceInstance) error {
	f := func() error {
		return epsd.serviceDiscovery.Register(instance)
	}
	return epsd.executeWithEvents(NewServiceInstancePreRegisteredEvent(epsd.serviceDiscovery, instance),
		f, NewServiceInstanceRegisteredEvent(epsd.serviceDiscovery, instance))

}

// Update returns the result of serviceDiscovery.Update
func (epsd *EventPublishingServiceDiscovery) Update(instance registry.ServiceInstance) error {
	f := func() error {
		return epsd.serviceDiscovery.Update(instance)
	}
	return epsd.executeWithEvents(nil, f, nil)
}

// Unregister unregister the instance and drop ServiceInstancePreUnregisteredEvent and ServiceInstanceUnregisteredEvent
func (epsd *EventPublishingServiceDiscovery) Unregister(instance registry.ServiceInstance) error {
	f := func() error {
		return epsd.serviceDiscovery.Unregister(instance)
	}
	return epsd.executeWithEvents(NewServiceInstancePreUnregisteredEvent(epsd.serviceDiscovery, instance),
		f, NewServiceInstanceUnregisteredEvent(epsd.serviceDiscovery, instance))
}

// GetDefaultPageSize returns the result of serviceDiscovery.GetDefaultPageSize
func (epsd *EventPublishingServiceDiscovery) GetDefaultPageSize() int {
	return epsd.serviceDiscovery.GetDefaultPageSize()
}

// GetServices returns the result of serviceDiscovery.GetServices
func (epsd *EventPublishingServiceDiscovery) GetServices() *gxset.HashSet {
	return epsd.serviceDiscovery.GetServices()
}

// GetInstances returns the result of serviceDiscovery.GetInstances
func (epsd *EventPublishingServiceDiscovery) GetInstances(serviceName string) []registry.ServiceInstance {
	return epsd.serviceDiscovery.GetInstances(serviceName)
}

// GetInstancesByPage returns the result of serviceDiscovery.GetInstancesByPage
func (epsd *EventPublishingServiceDiscovery) GetInstancesByPage(serviceName string, offset int, pageSize int) gxpage.Pager {
	return epsd.serviceDiscovery.GetInstancesByPage(serviceName, offset, pageSize)
}

// GetHealthyInstancesByPage returns the result of serviceDiscovery.GetHealthyInstancesByPage
func (epsd *EventPublishingServiceDiscovery) GetHealthyInstancesByPage(serviceName string, offset int, pageSize int, healthy bool) gxpage.Pager {
	return epsd.serviceDiscovery.GetHealthyInstancesByPage(serviceName, offset, pageSize, healthy)
}

// GetRequestInstances returns result from serviceDiscovery.GetRequestInstances
func (epsd *EventPublishingServiceDiscovery) GetRequestInstances(serviceNames []string, offset int, requestedSize int) map[string]gxpage.Pager {
	return epsd.serviceDiscovery.GetRequestInstances(serviceNames, offset, requestedSize)
}

// AddListener add event listener
func (epsd *EventPublishingServiceDiscovery) AddListener(listener *registry.ServiceInstancesChangedListener) error {
	extension.GetGlobalDispatcher().AddEventListener(listener)
	return epsd.serviceDiscovery.AddListener(listener)
}

// DispatchEventByServiceName pass serviceName to serviceDiscovery
func (epsd *EventPublishingServiceDiscovery) DispatchEventByServiceName(serviceName string) error {
	return epsd.serviceDiscovery.DispatchEventByServiceName(serviceName)
}

// DispatchEventForInstances pass params to serviceDiscovery
func (epsd *EventPublishingServiceDiscovery) DispatchEventForInstances(serviceName string, instances []registry.ServiceInstance) error {
	return epsd.serviceDiscovery.DispatchEventForInstances(serviceName, instances)
}

// DispatchEvent pass the event to serviceDiscovery
func (epsd *EventPublishingServiceDiscovery) DispatchEvent(event *registry.ServiceInstancesChangedEvent) error {
	return epsd.serviceDiscovery.DispatchEvent(event)
}

// executeWithEvents dispatch before event and after event if return error will dispatch exception event
func (epsd *EventPublishingServiceDiscovery) executeWithEvents(beforeEvent observer.Event, f func() error, afterEvent observer.Event) error {
	globalDispatcher := extension.GetGlobalDispatcher()
	if beforeEvent != nil {
		globalDispatcher.Dispatch(beforeEvent)
	}
	if err := f(); err != nil {
		globalDispatcher.Dispatch(NewServiceDiscoveryExceptionEvent(epsd, epsd.serviceDiscovery, err))
		return err
	}
	if afterEvent != nil {
		globalDispatcher.Dispatch(afterEvent)
	}
	return nil
}

// getMetadataService returns metadata service instance
func getMetadataService() (service.MetadataService, error) {
	return extension.GetMetadataService(config.GetApplicationConfig().MetadataType)
}
