// Path: src/com/jetbrains/crucible/configuration/CrucibleSettings.java
// @State(name = "CrucibleSettings",
//        storages = {
//          @Storage(file = "$APP_CONFIG$" + "/crucibleConnector.xml")
//        }
// )
// public class CrucibleSettings implements PersistentStateComponent<CrucibleSettings> {
//   public String SERVER_URL = "";
//   public String USERNAME = "";
// 
//   @Override
//   public CrucibleSettings getState() {
//     return this;
//   }
// 
//   @Override
//   public void loadState(CrucibleSettings state) {
//     XmlSerializerUtil.copyBean(state, this);
//   }
// 
//   public static CrucibleSettings getInstance() {
//     return ServiceManager.getService(CrucibleSettings.class);
//   }
// 
//   public static final String CRUCIBLE_SETTINGS_PASSWORD_KEY = "CRUCIBLE_SETTINGS_PASSWORD_KEY";
//   private static final Logger LOG = Logger.getInstance(CrucibleConfigurable.class.getName());
// 
//   public void savePassword(String pass) {
//     PasswordSafe.getInstance().set(new CredentialAttributes(CRUCIBLE_SETTINGS_PASSWORD_KEY), new Credentials(USERNAME, pass));
//   }
// 
//   @Nullable
//   public String getPassword() {
//     final Credentials credentials = PasswordSafe.getInstance().get(new CredentialAttributes(CRUCIBLE_SETTINGS_PASSWORD_KEY));
// 
//     return credentials != null ? credentials.getPasswordAsString() : null;
//   }
// }
// 
// Path: src/com/jetbrains/crucible/connection/exceptions/CrucibleApiException.java
// public class CrucibleApiException extends Exception {
// 
//   public CrucibleApiException(String message) {
//     super(message);
//   }
// 
//   public CrucibleApiException(String message, Throwable throwable) {
//     super(message, throwable);
//   }
// }
// 
// Path: src/com/jetbrains/crucible/connection/exceptions/CrucibleApiLoginException.java
// public class CrucibleApiLoginException extends CrucibleApiException {
// 
//   public CrucibleApiLoginException(String message) {
//     super(message);
//   }
// 
//   public CrucibleApiLoginException(String message, Throwable throwable) {
//     super(message, throwable);
//   }
// }
// 
// Path: src/com/jetbrains/crucible/ui/UiUtils.java
// public class UiUtils {
//   private UiUtils() {
//   }
// 
//   public static void showBalloon(@NotNull final Project project, @NotNull final String message,
//                                  @NotNull final MessageType messageType) {
//     final JFrame frame = WindowManager.getInstance().getFrame(project.isDefault() ? null : project);
//     if (frame == null) return;
//     final JComponent component = frame.getRootPane();
//     if (component == null) return;
//     final Rectangle rect = component.getVisibleRect();
//     final Point p = new Point(rect.x + rect.width - 10, rect.y + 10);
//     final RelativePoint point = new RelativePoint(component, p);
// 
//     final BalloonBuilder balloonBuilder = JBPopupFactory.getInstance().
//       createHtmlTextBalloonBuilder(message, messageType.getDefaultIcon(),
//                                    messageType.getPopupBackground(), null);
//     balloonBuilder.setShowCallout(false).setCloseButtonEnabled(true)
//                   .createBalloon().show(point, Balloon.Position.atLeft);
//   }
// }


import com.google.gson.*;
import com.intellij.dvcs.repo.VcsRepositoryManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.SLRUCache;
import com.jetbrains.crucible.configuration.CrucibleSettings;
import com.jetbrains.crucible.connection.exceptions.CrucibleApiException;
import com.jetbrains.crucible.connection.exceptions.CrucibleApiLoginException;
import com.jetbrains.crucible.model.*;
import com.jetbrains.crucible.ui.UiUtils;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.HttpMethodBase;
import org.apache.commons.httpclient.contrib.ssl.EasySSLProtocolSocketFactory;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
import org.apache.commons.httpclient.protocol.Protocol;
import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
import org.apache.commons.lang.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.*;
    }
    return null;
  }

  @Nullable
  public Comment postComment(@NotNull final Comment comment, boolean isGeneral,
                             @NotNull final String reviewId) {

    String url = getHostUrl() + REVIEW_SERVICE + "/" + reviewId;
    final String parentCommentId = comment.getParentCommentId();

    final boolean isVersioned = !isGeneral;
    boolean reply = comment.getParentCommentId() != null;

    if (isVersioned && !reply) {
      url += REVIEW_ITEMS + "/" + comment.getReviewItemId();
    }

    url += COMMENTS;

    if (reply) {
      url += "/" + parentCommentId + REPLIES;
    }

    try {
      final RequestEntity request = CrucibleApi.createCommentRequest(comment, !isVersioned);

      final JsonObject jsonObject = buildJsonResponseForPost(url, request);
      final String errorMessage = getExceptionMessages(jsonObject);
      if (errorMessage != null) {
// Path: src/com/jetbrains/crucible/configuration/CrucibleSettings.java
// @State(name = "CrucibleSettings",
//        storages = {
//          @Storage(file = "$APP_CONFIG$" + "/crucibleConnector.xml")
//        }
// )
// public class CrucibleSettings implements PersistentStateComponent<CrucibleSettings> {
//   public String SERVER_URL = "";
//   public String USERNAME = "";
// 
//   @Override
//   public CrucibleSettings getState() {
//     return this;
//   }
// 
//   @Override
//   public void loadState(CrucibleSettings state) {
//     XmlSerializerUtil.copyBean(state, this);
//   }
// 
//   public static CrucibleSettings getInstance() {
//     return ServiceManager.getService(CrucibleSettings.class);
//   }
// 
//   public static final String CRUCIBLE_SETTINGS_PASSWORD_KEY = "CRUCIBLE_SETTINGS_PASSWORD_KEY";
//   private static final Logger LOG = Logger.getInstance(CrucibleConfigurable.class.getName());
// 
//   public void savePassword(String pass) {
//     PasswordSafe.getInstance().set(new CredentialAttributes(CRUCIBLE_SETTINGS_PASSWORD_KEY), new Credentials(USERNAME, pass));
//   }
// 
//   @Nullable
//   public String getPassword() {
//     final Credentials credentials = PasswordSafe.getInstance().get(new CredentialAttributes(CRUCIBLE_SETTINGS_PASSWORD_KEY));
// 
//     return credentials != null ? credentials.getPasswordAsString() : null;
//   }
// }
// 
// Path: src/com/jetbrains/crucible/connection/exceptions/CrucibleApiException.java
// public class CrucibleApiException extends Exception {
// 
//   public CrucibleApiException(String message) {
//     super(message);
//   }
// 
//   public CrucibleApiException(String message, Throwable throwable) {
//     super(message, throwable);
//   }
// }
// 
// Path: src/com/jetbrains/crucible/connection/exceptions/CrucibleApiLoginException.java
// public class CrucibleApiLoginException extends CrucibleApiException {
// 
//   public CrucibleApiLoginException(String message) {
//     super(message);
//   }
// 
//   public CrucibleApiLoginException(String message, Throwable throwable) {
//     super(message, throwable);
//   }
// }
// 
// Path: src/com/jetbrains/crucible/ui/UiUtils.java
// public class UiUtils {
//   private UiUtils() {
//   }
// 
//   public static void showBalloon(@NotNull final Project project, @NotNull final String message,
//                                  @NotNull final MessageType messageType) {
//     final JFrame frame = WindowManager.getInstance().getFrame(project.isDefault() ? null : project);
//     if (frame == null) return;
//     final JComponent component = frame.getRootPane();
//     if (component == null) return;
//     final Rectangle rect = component.getVisibleRect();
//     final Point p = new Point(rect.x + rect.width - 10, rect.y + 10);
//     final RelativePoint point = new RelativePoint(component, p);
// 
//     final BalloonBuilder balloonBuilder = JBPopupFactory.getInstance().
//       createHtmlTextBalloonBuilder(message, messageType.getDefaultIcon(),
//                                    messageType.getPopupBackground(), null);
//     balloonBuilder.setShowCallout(false).setCloseButtonEnabled(true)
//                   .createBalloon().show(point, Balloon.Position.atLeft);
//   }
// }


// Path: src/com/jetbrains/crucible/connection/CrucibleSessionImpl.java
import com.google.gson.*;
import com.intellij.dvcs.repo.VcsRepositoryManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.SLRUCache;
import com.jetbrains.crucible.configuration.CrucibleSettings;
import com.jetbrains.crucible.connection.exceptions.CrucibleApiException;
import com.jetbrains.crucible.connection.exceptions.CrucibleApiLoginException;
import com.jetbrains.crucible.model.*;
import com.jetbrains.crucible.ui.UiUtils;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.HttpMethodBase;
import org.apache.commons.httpclient.contrib.ssl.EasySSLProtocolSocketFactory;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
import org.apache.commons.httpclient.protocol.Protocol;
import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
import org.apache.commons.lang.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.*;

    }
    return null;
  }

  @Nullable
  public Comment postComment(@NotNull final Comment comment, boolean isGeneral,
                             @NotNull final String reviewId) {

    String url = getHostUrl() + REVIEW_SERVICE + "/" + reviewId;
    final String parentCommentId = comment.getParentCommentId();

    final boolean isVersioned = !isGeneral;
    boolean reply = comment.getParentCommentId() != null;

    if (isVersioned && !reply) {
      url += REVIEW_ITEMS + "/" + comment.getReviewItemId();
    }

    url += COMMENTS;

    if (reply) {
      url += "/" + parentCommentId + REPLIES;
    }

    try {
      final RequestEntity request = CrucibleApi.createCommentRequest(comment, !isVersioned);

      final JsonObject jsonObject = buildJsonResponseForPost(url, request);
      final String errorMessage = getExceptionMessages(jsonObject);
      if (errorMessage != null) {
        UiUtils.showBalloon(myProject, "Sorry, comment wasn't added:\n" + errorMessage, MessageType.ERROR);