/*
 * 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 org.apache.servicecomb.core;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicLong;

import javax.ws.rs.core.Response.Status;

import org.apache.commons.lang3.StringUtils;
import org.apache.servicecomb.config.ConfigUtil;
import org.apache.servicecomb.config.priority.PriorityPropertyManager;
import org.apache.servicecomb.core.BootListener.BootEvent;
import org.apache.servicecomb.core.BootListener.EventType;
import org.apache.servicecomb.core.bootup.BootUpInformationCollector;
import org.apache.servicecomb.core.definition.ConsumerMicroserviceVersionsMeta;
import org.apache.servicecomb.core.definition.CoreMetaUtils;
import org.apache.servicecomb.core.definition.MicroserviceMeta;
import org.apache.servicecomb.core.definition.MicroserviceVersionsMeta;
import org.apache.servicecomb.core.definition.ServiceRegistryListener;
import org.apache.servicecomb.core.event.InvocationFinishEvent;
import org.apache.servicecomb.core.event.InvocationStartEvent;
import org.apache.servicecomb.core.executor.ExecutorManager;
import org.apache.servicecomb.core.filter.FilterChainsManager;
import org.apache.servicecomb.core.handler.ConsumerHandlerManager;
import org.apache.servicecomb.core.handler.HandlerConfigUtils;
import org.apache.servicecomb.core.handler.ProducerHandlerManager;
import org.apache.servicecomb.core.provider.consumer.ConsumerProviderManager;
import org.apache.servicecomb.core.provider.consumer.MicroserviceReferenceConfig;
import org.apache.servicecomb.core.provider.producer.ProducerProviderManager;
import org.apache.servicecomb.core.transport.TransportManager;
import org.apache.servicecomb.foundation.common.VendorExtensions;
import org.apache.servicecomb.foundation.common.event.EnableExceptionPropagation;
import org.apache.servicecomb.foundation.common.event.EventManager;
import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils;
import org.apache.servicecomb.foundation.vertx.VertxUtils;
import org.apache.servicecomb.foundation.vertx.client.http.HttpClients;
import org.apache.servicecomb.registry.DiscoveryManager;
import org.apache.servicecomb.registry.RegistrationManager;
import org.apache.servicecomb.registry.api.event.MicroserviceInstanceRegisteredEvent;
import org.apache.servicecomb.registry.api.registry.MicroserviceInstanceStatus;
import org.apache.servicecomb.registry.consumer.MicroserviceVersions;
import org.apache.servicecomb.registry.definition.MicroserviceNameParser;
import org.apache.servicecomb.registry.swagger.SwaggerLoader;
import org.apache.servicecomb.swagger.engine.SwaggerEnvironment;
import org.apache.servicecomb.swagger.invocation.exception.CommonExceptionData;
import org.apache.servicecomb.swagger.invocation.exception.InvocationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;

import com.google.common.eventbus.AllowConcurrentEvents;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
import com.netflix.config.DynamicPropertyFactory;

public class SCBEngine {
  private static final Logger LOGGER = LoggerFactory.getLogger(SCBEngine.class);

  static final String CFG_KEY_WAIT_UP_TIMEOUT = "servicecomb.boot.waitUp.timeoutInMilliseconds";

  static final long DEFAULT_WAIT_UP_TIMEOUT = 10_000;

  static final String CFG_KEY_TURN_DOWN_STATUS_WAIT_SEC = "servicecomb.boot.turnDown.waitInSeconds";

  static final long DEFAULT_TURN_DOWN_STATUS_WAIT_SEC = 0;

  private static final Object initializationLock = new Object();

  private static volatile SCBEngine INSTANCE;

  private ApplicationContext applicationContext;

  private FilterChainsManager filterChainsManager;

  private final ConsumerHandlerManager consumerHandlerManager = new ConsumerHandlerManager();

  private final ProducerHandlerManager producerHandlerManager = new ProducerHandlerManager();

  private ProducerProviderManager producerProviderManager;

  private ConsumerProviderManager consumerProviderManager = new ConsumerProviderManager();

  private MicroserviceMeta producerMicroserviceMeta;

  private TransportManager transportManager = new TransportManager();

  private final List<BootListener> bootListeners = new ArrayList<>(
      SPIServiceUtils.getOrLoadSortedService(BootListener.class));

  private final AtomicLong invocationStartedCounter = new AtomicLong();

  private final AtomicLong invocationFinishedCounter = new AtomicLong();

  private volatile SCBStatus status = SCBStatus.DOWN;

  private final EventBus eventBus;

  private ExecutorManager executorManager = new ExecutorManager();

  private PriorityPropertyManager priorityPropertyManager;

  protected List<BootUpInformationCollector> bootUpInformationCollectors = SPIServiceUtils
      .getSortedService(BootUpInformationCollector.class);

  private final ServiceRegistryListener serviceRegistryListener;

  private final SwaggerEnvironment swaggerEnvironment = new SwaggerEnvironment();

  private final VendorExtensions vendorExtensions = new VendorExtensions();

  private Thread shutdownHook;

  protected SCBEngine() {
    eventBus = EventManager.getEventBus();

    eventBus.register(this);

    INSTANCE = this;

    producerProviderManager = new ProducerProviderManager(this);
    serviceRegistryListener = new ServiceRegistryListener(this);
  }

  public ApplicationContext getApplicationContext() {
    return applicationContext;
  }

  public void setApplicationContext(ApplicationContext applicationContext) {
    this.applicationContext = applicationContext;
  }

  public VendorExtensions getVendorExtensions() {
    return vendorExtensions;
  }

  public String getAppId() {
    return RegistrationManager.INSTANCE.getAppId();
  }

  public void setStatus(SCBStatus status) {
    this.status = status;
  }

  public SCBStatus getStatus() {
    return status;
  }

  public static SCBEngine getInstance() {
    if (null == INSTANCE) {
      synchronized (initializationLock) {
        if (null == INSTANCE) {
          new SCBEngine();
        }
      }
    }
    return INSTANCE;
  }

  public SwaggerLoader getSwaggerLoader() {
    return RegistrationManager.INSTANCE.getSwaggerLoader();
  }

  public FilterChainsManager getFilterChainsManager() {
    return filterChainsManager;
  }

  public SCBEngine setFilterChainsManager(FilterChainsManager filterChainsManager) {
    this.filterChainsManager = filterChainsManager;
    return this;
  }

  public boolean isFilterChainEnabled() {
    return filterChainsManager.isEnabled();
  }

  public ConsumerHandlerManager getConsumerHandlerManager() {
    return consumerHandlerManager;
  }

  public ProducerHandlerManager getProducerHandlerManager() {
    return producerHandlerManager;
  }

  public PriorityPropertyManager getPriorityPropertyManager() {
    return priorityPropertyManager;
  }

  public SCBEngine setPriorityPropertyManager(PriorityPropertyManager priorityPropertyManager) {
    this.priorityPropertyManager = priorityPropertyManager;
    return this;
  }

  public EventBus getEventBus() {
    return eventBus;
  }

  public ExecutorManager getExecutorManager() {
    return executorManager;
  }

  public void setExecutorManager(ExecutorManager executorManager) {
    this.executorManager = executorManager;
  }

  public ProducerProviderManager getProducerProviderManager() {
    return producerProviderManager;
  }

  public void setProducerProviderManager(ProducerProviderManager producerProviderManager) {
    this.producerProviderManager = producerProviderManager;
  }

  public ConsumerProviderManager getConsumerProviderManager() {
    return consumerProviderManager;
  }

  public SCBEngine setConsumerProviderManager(ConsumerProviderManager consumerProviderManager) {
    this.consumerProviderManager = consumerProviderManager;
    return this;
  }

  public TransportManager getTransportManager() {
    return transportManager;
  }

  public SCBEngine setTransportManager(TransportManager transportManager) {
    this.transportManager = transportManager;
    return this;
  }

  public SwaggerEnvironment getSwaggerEnvironment() {
    return swaggerEnvironment;
  }

  public Collection<BootListener> getBootListeners() {
    return bootListeners;
  }

  public void addBootListeners(Collection<BootListener> bootListeners) {
    this.bootListeners.addAll(bootListeners);
  }

  public SCBEngine addProducerMeta(String schemaId, Object instance) {
    getProducerProviderManager().addProducerMeta(schemaId, instance);
    return this;
  }

  protected void triggerEvent(EventType eventType) {
    BootEvent event = new BootEvent();
    event.setScbEngine(this);
    event.setEventType(eventType);

    for (BootListener listener : bootListeners) {
      listener.onBootEvent(event);
    }
  }

  protected void safeTriggerEvent(EventType eventType) {
    BootEvent event = new BootEvent();
    event.setScbEngine(this);
    event.setEventType(eventType);

    for (BootListener listener : bootListeners) {
      try {
        listener.onBootEvent(event);
        LOGGER.info("BootListener {} succeed to process {}.", listener.getClass().getName(), eventType);
      } catch (Throwable e) {
        LOGGER.error("BootListener {} failed to process {}.", listener.getClass().getName(), eventType, e);
      }
    }
  }

  /**
   * <p>As the process of instance registry is asynchronous, the {@code AFTER_REGISTRY}
   * event should not be sent immediately.
   * When the instance registry succeeds, {@link MicroserviceInstanceRegisteredEvent} will be posted in {@link EventManager},
   * register a subscriber to watch this event and send {@code AFTER_REGISTRY}.</p>
   *
   * <p>This method should be called before registry initialization to avoid that the registry process is too quick
   * that the event is not watched by this subscriber.</p>
   *
   * <p>Check if {@code InstanceId} is null to judge whether the instance registry has succeeded.</p>
   */
  private void triggerAfterRegistryEvent() {
    eventBus.register(new AfterRegistryEventHanlder(this));
  }

  @AllowConcurrentEvents
  @Subscribe
  public void onInvocationStart(InvocationStartEvent event) {
    invocationStartedCounter.incrementAndGet();
  }

  @AllowConcurrentEvents
  @Subscribe
  public void onInvocationFinish(InvocationFinishEvent event) {
    invocationFinishedCounter.incrementAndGet();
  }

  public synchronized SCBEngine run() {
    if (SCBStatus.DOWN.equals(status)) {
      try {
        doRun();
        waitStatusUp();
      } catch (TimeoutException e) {
        LOGGER.warn("{}", e.getMessage());
      } catch (Throwable e) {
        LOGGER.error("Failed to start ServiceComb due to errors and close", e);
        try {
          destroy();
        } catch (Exception exception) {
          LOGGER.info("destroy has some error.", exception);
        }
        status = SCBStatus.FAILED;
        throw new IllegalStateException("ServiceComb init failed.", e);
      } finally {
        printServiceInfo();
      }
    }

    return this;
  }

  private void printServiceInfo() {
    StringBuilder serviceInfo = new StringBuilder();
    serviceInfo.append("Service information is shown below:\n");
    for (BootUpInformationCollector bootUpInformationCollector : bootUpInformationCollectors) {
      String info = bootUpInformationCollector.collect(this);
      if (StringUtils.isEmpty(info)) {
        continue;
      }

      serviceInfo.append(info);
      if (!info.endsWith("\n")) {
        serviceInfo.append('\n');
      }
    }
    LOGGER.info(serviceInfo.toString());
  }

  private void doRun() throws Exception {
    status = SCBStatus.STARTING;

    bootListeners.sort(Comparator.comparingInt(BootListener::getOrder));

    triggerEvent(EventType.BEFORE_HANDLER);
    HandlerConfigUtils.init(consumerHandlerManager, producerHandlerManager);
    triggerEvent(EventType.AFTER_HANDLER);

    triggerEvent(EventType.BEFORE_FILTER);
    filterChainsManager.init();
    triggerEvent(EventType.AFTER_FILTER);

    createProducerMicroserviceMeta();

    triggerEvent(EventType.BEFORE_PRODUCER_PROVIDER);
    producerProviderManager.init();
    triggerEvent(EventType.AFTER_PRODUCER_PROVIDER);

    triggerEvent(EventType.BEFORE_CONSUMER_PROVIDER);
    consumerProviderManager.init();
    triggerEvent(EventType.AFTER_CONSUMER_PROVIDER);

    triggerEvent(EventType.BEFORE_TRANSPORT);
    transportManager.init(this);
    triggerEvent(EventType.AFTER_TRANSPORT);

    triggerEvent(EventType.BEFORE_REGISTRY);

    triggerAfterRegistryEvent();

    RegistrationManager.INSTANCE.run();
    DiscoveryManager.INSTANCE.run();

    shutdownHook = new Thread(this::destroyForShutdownHook);
    Runtime.getRuntime().addShutdownHook(shutdownHook);
  }

  private void createProducerMicroserviceMeta() {
    String microserviceName = RegistrationManager.INSTANCE.getMicroservice().getServiceName();

    producerMicroserviceMeta = new MicroserviceMeta(this, microserviceName, false);
    producerMicroserviceMeta.setHandlerChain(producerHandlerManager.getOrCreate(microserviceName));
    producerMicroserviceMeta.setFilterChain(filterChainsManager.findProducerChain(microserviceName));
    producerMicroserviceMeta.setMicroserviceVersionsMeta(new MicroserviceVersionsMeta(this, microserviceName));
  }

  public void destroyForShutdownHook() {
    shutdownHook = null;
    destroy();
  }

  /**
   * not allow throw any exception
   * even some step throw exception, must catch it and go on, otherwise shutdown process will be broken.
   */
  public synchronized void destroy() {
    if (SCBStatus.UP.equals(status) || SCBStatus.STARTING.equals(status)) {
      LOGGER.info("ServiceComb is closing now...");
      doDestroy();
      status = SCBStatus.DOWN;
      LOGGER.info("ServiceComb had closed");
    }
  }

  private void doDestroy() {
    if (shutdownHook != null) {
      Runtime.getRuntime().removeShutdownHook(shutdownHook);
    }

    //Step 0: turn down the status of this instance in service center,
    // so that the consumers can remove this instance record in advance
    turnDownInstanceStatus();
    blockShutDownOperationForConsumerRefresh();

    //Step 1: notify all component stop invoke via BEFORE_CLOSE Event
    safeTriggerEvent(EventType.BEFORE_CLOSE);

    //Step 2: forbid create new consumer invocation
    status = SCBStatus.STOPPING;

    //Step 3: Unregister microservice instance from Service Center and close vertx
    // Forbidden other consumers find me
    RegistrationManager.INSTANCE.destroy();
    DiscoveryManager.INSTANCE.destroy();

    serviceRegistryListener.destroy();

    //Step 4: wait all invocation finished
    try {
      validAllInvocationFinished();
    } catch (InterruptedException e) {
      LOGGER.error("wait all invocation finished interrupted", e);
    }

    //Step 5: destroy config center source
    ConfigUtil.destroyConfigCenterConfigurationSource();
    // only be null for some test cases
    if (priorityPropertyManager != null) {
      priorityPropertyManager.close();
    }

    //Step 6: Stop vertx to prevent blocking exit
    // delete the following one line when every refactor is done.
    VertxUtils.blockCloseVertxByName("transport");

    HttpClients.destroy();

    //Step 7: notify all component do clean works via AFTER_CLOSE Event
    safeTriggerEvent(EventType.AFTER_CLOSE);
  }

  private void turnDownInstanceStatus() {
    RegistrationManager.INSTANCE.updateMicroserviceInstanceStatus(MicroserviceInstanceStatus.DOWN);
  }

  private void blockShutDownOperationForConsumerRefresh() {
    try {
      long turnDownWaitSeconds = DynamicPropertyFactory.getInstance()
          .getLongProperty(CFG_KEY_TURN_DOWN_STATUS_WAIT_SEC, DEFAULT_TURN_DOWN_STATUS_WAIT_SEC)
          .get();
      if (turnDownWaitSeconds <= 0) {
        return;
      }
      Thread.sleep(TimeUnit.SECONDS.toMillis(turnDownWaitSeconds));
    } catch (InterruptedException e) {
      LOGGER.warn("failed to block the shutdown procedure", e);
    }
  }

  private void validAllInvocationFinished() throws InterruptedException {
    long start = System.currentTimeMillis();
    while (true) {
      long remaining = invocationStartedCounter.get() - invocationFinishedCounter.get();
      if (remaining <= 0) {
        return;
      }

      if (System.currentTimeMillis() - start > TimeUnit.SECONDS.toMillis(30)) {
        LOGGER.error("wait for all requests timeout, abandon waiting, remaining requests: {}.", remaining);
        return;
      }
      TimeUnit.SECONDS.sleep(1);
    }
  }

  public void ensureStatusUp() {
    SCBStatus currentStatus = getStatus();
    if (!SCBStatus.UP.equals(currentStatus)) {
      String message =
          "The request is rejected. Cannot process the request due to STATUS = " + currentStatus;
      LOGGER.warn(message);
      throw new InvocationException(Status.SERVICE_UNAVAILABLE, new CommonExceptionData(message));
    }
  }

  /**
   * for normal consumers
   * @param microserviceName shortName, or appId:shortName when invoke cross app
   * @return
   */
  public MicroserviceReferenceConfig createMicroserviceReferenceConfig(String microserviceName) {
    return createMicroserviceReferenceConfig(microserviceName, null);
  }

  /**
   * for edge, versionRule maybe controlled by url rule
   * @param microserviceName hortName, or appId:shortName when invoke cross app
   * @param versionRule if is empty, then use configuration value
   * @return
   */
  public CompletableFuture<MicroserviceReferenceConfig> createMicroserviceReferenceConfigAsync(String microserviceName,
      String versionRule) {
    return DiscoveryManager.INSTANCE
        .getOrCreateMicroserviceVersionsAsync(parseAppId(microserviceName), microserviceName)
        .thenApply(versions -> {
          ConsumerMicroserviceVersionsMeta microserviceVersionsMeta = CoreMetaUtils
              .getMicroserviceVersionsMeta(versions);
          return new MicroserviceReferenceConfig(microserviceVersionsMeta, versionRule);
        });
  }

  /**
   * for edge, versionRule maybe controlled by url rule
   * @param microserviceName hortName, or appId:shortName when invoke cross app
   * @param versionRule if is empty, then use configuration value
   * @return
   */
  public MicroserviceReferenceConfig createMicroserviceReferenceConfig(String microserviceName, String versionRule) {
    ensureStatusUp();
    MicroserviceVersions microserviceVersions = DiscoveryManager.INSTANCE
        .getOrCreateMicroserviceVersions(parseAppId(microserviceName), microserviceName);
    ConsumerMicroserviceVersionsMeta microserviceVersionsMeta = CoreMetaUtils
        .getMicroserviceVersionsMeta(microserviceVersions);

    return new MicroserviceReferenceConfig(microserviceVersionsMeta, versionRule);
  }

  public MicroserviceMeta getProducerMicroserviceMeta() {
    return producerMicroserviceMeta;
  }

  public void setProducerMicroserviceMeta(MicroserviceMeta producerMicroserviceMeta) {
    this.producerMicroserviceMeta = producerMicroserviceMeta;
  }

  /**
   * better to subscribe EventType.AFTER_REGISTRY by BootListener<br>
   * but in some simple scenes, just block and wait is enough.
   */
  public void waitStatusUp() throws InterruptedException, TimeoutException {
    long msWait = DynamicPropertyFactory.getInstance().getLongProperty(CFG_KEY_WAIT_UP_TIMEOUT, DEFAULT_WAIT_UP_TIMEOUT)
        .get();
    waitStatusUp(msWait);
  }

  /**
   * better to subscribe EventType.AFTER_REGISTRY by BootListener<br>
   * but in some simple scenes, just block and wait is enough.
   */
  public void waitStatusUp(long msWait) throws InterruptedException, TimeoutException {
    if (msWait <= 0) {
      LOGGER.info("Give up waiting for status up, wait timeout milliseconds={}.", msWait);
      return;
    }

    LOGGER.info("Waiting for status up. timeout: {}ms", msWait);
    long start = System.currentTimeMillis();
    for (; ; ) {
      SCBStatus currentStatus = getStatus();
      switch (currentStatus) {
        case DOWN:
        case FAILED:
          throw new IllegalStateException("Failed to wait status up, real status: " + currentStatus);
        case UP:
          LOGGER.info("Status already changed to up.");
          return;
        default:
          break;
      }

      TimeUnit.MILLISECONDS.sleep(100);
      if (System.currentTimeMillis() - start > msWait) {
        throw new TimeoutException(
            String.format("Timeout to wait status up, timeout: %dms, last status: %s", msWait, currentStatus));
      }
    }
  }

  public String parseAppId(String microserviceName) {
    return parseMicroserviceName(microserviceName).getAppId();
  }

  public MicroserviceNameParser parseMicroserviceName(String microserviceName) {
    return new MicroserviceNameParser(getAppId(), microserviceName);
  }

  public static class AfterRegistryEventHanlder {
    private final SCBEngine engine;

    public AfterRegistryEventHanlder(SCBEngine engine) {
      this.engine = engine;
    }

    @Subscribe
    @EnableExceptionPropagation
    public void afterRegistryInstance(MicroserviceInstanceRegisteredEvent event) {
      if (event.isRegistrationManager()) {
        LOGGER.info("instance registry succeeds for the first time, will send AFTER_REGISTRY event.");
        engine.setStatus(SCBStatus.UP);
        engine.triggerEvent(EventType.AFTER_REGISTRY);
        EventManager.unregister(this);
        // keep this message to be WARN, used to detect service ready.
        LOGGER.warn("ServiceComb is ready.");
      }
    }
  }
}
