/*
 * 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.http.client.common;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import org.apache.commons.lang.StringUtils;
import org.apache.servicecomb.http.client.event.RefreshEndpointEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.util.concurrent.ThreadFactoryBuilder;

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

  public static final String DEFAULT_PROJECT = "default";

  public static final String V4_PREFIX = "/v4/";

  private static final String V3_PREFIX = "/v3/";

  private static final int DEFAULT_METRICS_WINDOW_TIME = 1;

  private static final int ISOLATION_THRESHOLD = 3;

  private List<String> addresses = new ArrayList<>();

  private int index = 0;

  private String projectName;

  private Map<String, Boolean> categoryMap = new HashMap<>();

  private Map<String, Integer> recodeStatus = new ConcurrentHashMap<>();

  private Map<String, Boolean> history = new ConcurrentHashMap<>();

  private volatile List<String> availableZone = new ArrayList<>();

  private volatile List<String> availableRegion = new ArrayList<>();

  private volatile List<String> defaultAddress = new ArrayList<>();

  private boolean isAddressRefresh = false;

  private final Object lock = new Object();

  private ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1,
      new ThreadFactoryBuilder()
          .setNameFormat("check-available-address-%d")
          .build());

  private Cache<String, Boolean> cacheAddress = CacheBuilder.newBuilder()
      .maximumSize(100)
      .expireAfterWrite(10, TimeUnit.MINUTES)
      .build();

  public AbstractAddressManager(List<String> addresses) {
    this.addresses.addAll(addresses);
  }

  public AbstractAddressManager(String projectName, List<String> addresses) {
    this.projectName = StringUtils.isEmpty(projectName) ? DEFAULT_PROJECT : projectName;
    this.addresses = this.transformAddress(addresses);
    this.defaultAddress = this.addresses;
  }

  @VisibleForTesting
  protected void setAddressRefresh(boolean addressRefresh) {
    isAddressRefresh = addressRefresh;
  }

  private void startCheck() {
    executorService.scheduleAtFixedRate(this::checkHistory,
        0,
        DEFAULT_METRICS_WINDOW_TIME,
        TimeUnit.MINUTES);
  }

  public String formatUrl(String url, boolean absoluteUrl, String address) {
    return absoluteUrl ? address + url : formatAddress(address) + url;
  }

  // if isAddressRefresh is false, polling with available initial addresses.
  public String address() {
    if (!isAddressRefresh) {
      return getDefaultAddress();
    } else {
      return getAvailableZoneAddress();
    }
  }

  public boolean sslEnabled() {
    return address().startsWith("https://");
  }

  protected List<String> transformAddress(List<String> addresses) {
    return addresses.stream().map(this::formatAddress).collect(Collectors.toList());
  }

  protected String getUrlPrefix(String address) {
    return address + V3_PREFIX;
  }

  protected String formatAddress(String address) {
    try {
      return getUrlPrefix(address) + HttpUtils.encodeURLParam(this.projectName);
    } catch (Exception e) {
      throw new IllegalStateException("not possible");
    }
  }

  private String getDefaultAddress() {
    List<String> addresses = getAvailableAddress(defaultAddress);
    if (!addresses.isEmpty()) {
      return getCurrentAddress(addresses);
    }
    return getInitAddress();
  }

  private String getAvailableZoneAddress() {
    List<String> addresses = getAvailableZoneIpPorts();
    if (!addresses.isEmpty()) {
      return joinProject(getCurrentAddress(addresses));
    }
    return getInitAddress();
  }

  // when all available address is fail, it will use all the initial addresses for polling.
  private String getInitAddress() {
    if (addresses.isEmpty()) {
      return null;
    }
    return getCurrentAddress(addresses);
  }

  private String getCurrentAddress(List<String> addresses) {
    synchronized (this) {
      this.index++;
      if (this.index >= addresses.size()) {
        this.index = 0;
      }
      return addresses.get(index);
    }
  }

  protected String joinProject(String address) {
    return address;
  }

  private List<String> getAvailableZoneIpPorts() {
    List<String> results = new ArrayList<>();
    if (!availableZone.isEmpty()) {
      results.addAll(getAvailableAddress(availableZone));
    } else {
      results.addAll(getAvailableAddress(availableRegion));
    }
    return results;
  }

  private List<String> getAvailableAddress(List<String> endpoints) {
    List<String> list = endpoints.stream().filter(uri -> !history.containsKey(uri))
        .collect(Collectors.toList());
    return list;
  }

  protected String normalizeUri(String endpoint) {
    return new URLEndPoint(endpoint).toString();
  }

  public void refreshEndpoint(RefreshEndpointEvent event, String key) {
    this.setAddressRefresh(true);
    if (null == event || !event.getName().equals(key)) {
      return;
    }
    availableZone = event.getSameZone().stream().map(this::normalizeUri).collect(Collectors.toList());
    availableRegion = event.getSameRegion().stream().map(this::normalizeUri).collect(Collectors.toList());
    availableZone.forEach(address -> categoryMap.put(address, true));
    availableRegion.forEach(address -> categoryMap.put(address, false));
    startCheck();
  }

  public void recordFailState(String address) {
    if (!recodeStatus.containsKey(address)) {
      recodeStatus.put(address, 1);
      return;
    }
    synchronized (lock) {
      int number = recodeStatus.get(address) + 1;
      if (number < ISOLATION_THRESHOLD) {
        recodeStatus.put(address, number);
      } else {
        removeAddress(address);
      }
    }
  }

  public void recordSuccessState(String address) {
    recodeStatus.put(address, 0);
  }

  @VisibleForTesting
  protected void checkHistory() {
    history.keySet().stream().filter(this::judgeIsolation).forEach(s -> {
      if (telnetTest(s)) {
        rejoinAddress(s);
      } else {
        cacheAddress.put(s, false);
      }
    });
  }

  private Boolean judgeIsolation(String address) {
    try {
      return cacheAddress.get(address, () -> true);
    } catch (ExecutionException e) {
      return true;
    }
  }

  private boolean telnetTest(String address) {
    URI ipPort = parseIpPortFromURI(address);
    try (Socket s = new Socket()) {
      s.connect(new InetSocketAddress(ipPort.getHost(), ipPort.getPort()), 3000);
      return true;
    } catch (IOException e) {
      LOGGER.warn("ping endpoint {} failed, It will be quarantined again.", address);
    }
    return false;
  }

  private URI parseIpPortFromURI(String uri) {
    try {
      return new URI(uri);
    } catch (URISyntaxException e) {
      return null;
    }
  }

  //Query whether the current address belongs to the same AZ or region through azmap,
  // add it to the sequence of, and delete the record in history
  @VisibleForTesting
  void rejoinAddress(String address) {
    if (!isAddressRefresh) {
      defaultAddress.add(address);
    } else {
      if (categoryMap.get(address)) {
        availableZone.add(address);
      } else {
        availableRegion.add(address);
      }
    }
    recodeStatus.put(address, 0);
    history.remove(address);
  }

  //Query whether the current address belongs to the same AZ or the same region through AZMap,
  // and delete it from the record. At the same time, add records in history and cache
  @VisibleForTesting
  void removeAddress(String address) {
    if (!isAddressRefresh) {
      defaultAddress.remove(address);
      history.put(address, false);
    } else {
      if (categoryMap.get(address)) {
        availableZone.remove(address);
      } else {
        availableRegion.remove(address);
      }
      history.put(address, categoryMap.get(address));
    }
    recodeStatus.put(address, 0);
    cacheAddress.put(address, false);
  }
}
