// Copyright (C) 2013 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.googlesource.gerrit.plugins.github.wizard;

import com.google.gerrit.server.IdentifiedUser;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import com.googlesource.gerrit.plugins.github.GitHubConfig;
import com.googlesource.gerrit.plugins.github.GitHubConfig.NextPage;
import com.googlesource.gerrit.plugins.github.oauth.GitHubLogin;
import com.googlesource.gerrit.plugins.github.oauth.ScopedProvider;
import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.http.HttpStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Singleton
public class VelocityControllerServlet extends HttpServlet {
  private static final long serialVersionUID = 5565594120346641704L;
  private static final Logger log = LoggerFactory.getLogger(VelocityControllerServlet.class);
  private static final String CONTROLLER_PACKAGE =
      VelocityControllerServlet.class.getPackage().getName();
  private final ScopedProvider<GitHubLogin> loginProvider;
  private final Provider<IdentifiedUser> userProvider;
  private final Injector injector;
  private final Provider<ControllerErrors> errorsProvider;
  private final GitHubConfig githubConfig;

  @Inject
  public VelocityControllerServlet(
      final ScopedProvider<GitHubLogin> loginProvider,
      Provider<IdentifiedUser> userProvider,
      final Injector injector,
      Provider<ControllerErrors> errorsProvider,
      GitHubConfig githubConfig) {
    this.loginProvider = loginProvider;
    this.userProvider = userProvider;
    this.injector = injector;
    this.errorsProvider = errorsProvider;
    this.githubConfig = githubConfig;
  }

  @SuppressWarnings("unchecked")
  @Override
  protected void service(HttpServletRequest req, HttpServletResponse resp)
      throws ServletException, IOException {
    String controllerName;
    VelocityController controller;
    controllerName = getControllerClassName(req);

    try {
      Class<? extends VelocityController> controllerClass =
          (Class<? extends VelocityController>)
              Class.forName(CONTROLLER_PACKAGE + "." + controllerName + "Controller");
      controller = injector.getInstance(controllerClass);
    } catch (ClassNotFoundException e) {
      log.debug("Cannot find any controller for servlet " + req.getServletPath());
      redirectToNextStep(req, resp);
      return;
    }

    GitHubLogin hubLogin = loginProvider.get(req);
    IdentifiedUser user = userProvider.get();
    WrappedResponse wrappedResp = new WrappedResponse(resp);
    controller.doAction(user, hubLogin, req, wrappedResp, errorsProvider.get());

    if (wrappedResp.getStatus() == 0 || wrappedResp.getStatus() == HttpStatus.SC_OK) {
      redirectToNextStep(req, resp);
    }
  }

  private String getControllerClassName(HttpServletRequest req) {
    String reqServletName;
    StringBuilder controllerName = new StringBuilder();
    reqServletName = req.getPathInfo();
    reqServletName = trimFromChar(reqServletName, '/');
    reqServletName = trimUpToChar(reqServletName, '.');
    String[] controllerNameParts = reqServletName.split("-");

    for (String namePart : controllerNameParts) {
      controllerName.append(Character.toUpperCase(namePart.charAt(0)) + namePart.substring(1));
    }
    return controllerName.toString();
  }

  private String trimUpToChar(String string, char ch) {
    if (string.indexOf(ch) >= 0) {
      return string.substring(0, string.indexOf(ch));
    }
    return string;
  }

  private String trimFromChar(String string, char ch) {
    if (string.lastIndexOf(ch) >= 0) {
      return string.substring(string.lastIndexOf(ch) + 1);
    }
    return string;
  }

  private void redirectToNextStep(HttpServletRequest req, HttpServletResponse resp)
      throws IOException, ServletException {
    String sourceUri = req.getPathInfo();
    int pathPos = sourceUri.lastIndexOf('/') + 1;
    String sourcePage = sourceUri.substring(pathPos);
    String sourcePath = sourceUri.substring(0, pathPos);
    int queryStringStart = sourcePage.indexOf('?');
    if (queryStringStart > 0) {
      sourcePage = sourcePage.substring(0, queryStringStart);
    }
    NextPage nextPage = githubConfig.getNextPage(sourcePage);
    if (nextPage != null) {
      if (nextPage.redirect) {
        resp.sendRedirect(nextPageURL(sourcePath, nextPage));
      } else {
        RequestDispatcher requestDispatcher =
            req.getRequestDispatcher(nextPageURL(sourcePath, nextPage));
        req.setAttribute("destUrl", nextPage.uri);
        requestDispatcher.forward(req, resp);
      }
    }
  }

  private String nextPageURL(String sourcePath, NextPage nextPage) {
    return nextPage.uri.startsWith("/") ? nextPage.uri : sourcePath + nextPage.uri;
  }
}
