package jetbrains.buildServer.profile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import jetbrains.buildServer.controllers.ActionErrors;
import jetbrains.buildServer.controllers.AjaxRequestProcessor;
import jetbrains.buildServer.controllers.BaseController;
import jetbrains.buildServer.serverSide.SBuildServer;
import jetbrains.buildServer.web.openapi.WebControllerManager;
import jetbrains.buildServer.web.openapi.WebResourcesManager;
import jetbrains.buildServer.log.Loggers;
import org.jdom.Element;
import org.jetbrains.annotations.Nullable;
import org.springframework.web.servlet.ModelAndView;

public class ProfilerController extends BaseController {
  private final Profiler myProfiler;

  public ProfilerController(final SBuildServer server, WebControllerManager manager,
                            Profiler profiler, WebResourcesManager webResources) {
    super(server);
    myProfiler = profiler;
    manager.registerController("/profiler.html", this);
    webResources.addPluginResources("serverProfile", "serverProfile.jar");
  }

  @Nullable
  protected ModelAndView doHandle(final HttpServletRequest request, final HttpServletResponse response) throws Exception {
    new AjaxRequestProcessor().processRequest(request, response, new AjaxRequestProcessor.RequestHandler() {
      public void handleRequest(final HttpServletRequest request, final HttpServletResponse response, final Element xmlResponse) {
        try {
          doAction(request);
        } catch (Exception e) {
          Loggers.SERVER.warn(e);
          ActionErrors errors = new ActionErrors();
          errors.addError("profilerProblem", getMessageWithNested(e));
          errors.serialize(xmlResponse);
        }
      }
    });

    return null;
  }

  static private String getMessageWithNested(Throwable e) {
    String result = e.getMessage();
    Throwable cause = e.getCause();
    if (cause != null) {
      result += " Caused by: " + getMessageWithNested(cause);
    }
    return result;
  }

  private void doAction(final HttpServletRequest request) throws Exception {
    String action = request.getParameter("profilerAction");
    if ("StartCpu".equals(action)) {
      myProfiler.startProfiler();
    } else if ("CaptureCPU".equals(action)) {
      try {
        String result = myProfiler.captureAndStop();
        addSuccessMessage(request, "CPU snapshot is saved to the file on the server: '" + result + "'");
      } catch (Exception e) {
        throw new Exception("Cannot capture CPU snapshot.", e);
      }
    } else if ("StopCPU".equals(action)) {
      myProfiler.stopProfiler();
    } else if ("CaptureMemory".equals(action)) {
      try {
        String result = myProfiler.captureMemorySnapshot();
        addSuccessMessage(request, "Memory snapshot is saved to the file on the server: '" + result + "'");
      } catch (Exception e) {
        throw new Exception("Cannot capture memory snapshot.", e);
      }
    }
  }

  private void addSuccessMessage(HttpServletRequest request, String result) {
    if (result != null) {
      getOrCreateMessages(request).addMessage("profilerMessage", result);
    }
  }
}
