// Copyright (C) 2017 The Android Open Source Project
//
// Licensed 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 com.ericsson.gerrit.plugins.highavailability.forwarder.rest;

import static javax.servlet.http.HttpServletResponse.SC_CONFLICT;
import static javax.servlet.http.HttpServletResponse.SC_NO_CONTENT;

import com.ericsson.gerrit.plugins.highavailability.forwarder.Context;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.server.index.account.AccountIndexer;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Singleton
class IndexAccountRestApiServlet extends HttpServlet {
  private static final long serialVersionUID = -1L;
  private static final Logger logger = LoggerFactory.getLogger(IndexAccountRestApiServlet.class);
  private static final Map<Account.Id, AtomicInteger> accountIdLocks = new HashMap<>();

  private final AccountIndexer indexer;

  @Inject
  IndexAccountRestApiServlet(AccountIndexer indexer) {
    this.indexer = indexer;
  }

  @Override
  protected void doPost(HttpServletRequest req, HttpServletResponse rsp)
      throws IOException, ServletException {
    rsp.setContentType("text/plain");
    rsp.setCharacterEncoding("UTF-8");
    String path = req.getPathInfo();
    String accountId = path.substring(path.lastIndexOf('/') + 1);
    Account.Id id = Account.Id.parse(accountId);
    try {
      Context.setForwardedEvent(true);
      index(id);
      rsp.setStatus(SC_NO_CONTENT);
    } catch (IOException e) {
      sendError(rsp, SC_CONFLICT, e.getMessage());
      logger.error("Unable to update account index", e);
    } finally {
      Context.unsetForwardedEvent();
    }
  }

  private static void sendError(HttpServletResponse rsp, int statusCode, String message) {
    try {
      rsp.sendError(statusCode, message);
    } catch (IOException e) {
      logger.error("Failed to send error messsage: " + e.getMessage(), e);
    }
  }

  private void index(Account.Id id) throws IOException {
    AtomicInteger accountIdLock = getAndIncrementAccountIdLock(id);
    synchronized (accountIdLock) {
      indexer.index(id);
      logger.debug("Account {} successfully indexed", id);
    }
    if (accountIdLock.decrementAndGet() == 0) {
      removeAccountIdLock(id);
    }
  }

  private AtomicInteger getAndIncrementAccountIdLock(Account.Id id) {
    synchronized (accountIdLocks) {
      AtomicInteger accountIdLock = accountIdLocks.get(id);
      if (accountIdLock == null) {
        accountIdLock = new AtomicInteger(1);
        accountIdLocks.put(id, accountIdLock);
      } else {
        accountIdLock.incrementAndGet();
      }
      return accountIdLock;
    }
  }

  private void removeAccountIdLock(Account.Id id) {
    synchronized (accountIdLocks) {
      if (accountIdLocks.get(id).get() == 0) {
        accountIdLocks.remove(id);
      }
    }
  }
}
