package com.intellij.tasks.youtrack;

import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.io.StreamUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.tasks.*;
import com.intellij.tasks.impl.BaseRepository;
import com.intellij.tasks.impl.BaseRepositoryImpl;
import com.intellij.tasks.impl.LocalTaskImpl;
import com.intellij.tasks.impl.TaskUtil;
import com.intellij.util.NullableFunction;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.text.VersionComparatorUtil;
import com.intellij.util.xmlb.annotations.MapAnnotation;
import com.intellij.util.xmlb.annotations.Property;
import com.intellij.util.xmlb.annotations.Tag;
import org.apache.axis.utils.XMLChar;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.UsernamePasswordCredentials;
import org.apache.commons.httpclient.auth.AuthScope;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import java.io.InputStream;
import java.io.StringReader;
import java.util.Date;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;

/**
 * @author Dmitry Avdeev
 */
@Tag("YouTrack")
public class YouTrackRepository extends BaseRepositoryImpl {

  private String myDefaultSearch = "Assignee: me sort by: updated #Unresolved";
  private Map<TaskState, String> myCustomStateNames = new EnumMap<TaskState, String>(TaskState.class);

  // Default names for supported issues states
  {
    myCustomStateNames.put(TaskState.IN_PROGRESS, "In Progress");
    myCustomStateNames.put(TaskState.RESOLVED, "Fixed");
  }

  /**
   * for serialization
   */
  @SuppressWarnings({"UnusedDeclaration"})
  public YouTrackRepository() {
  }

  public YouTrackRepository(TaskRepositoryType type) {
    super(type);
  }

  @NotNull
  @Override
  public BaseRepository clone() {
    return new YouTrackRepository(this);
  }

  private YouTrackRepository(YouTrackRepository other) {
    super(other);
    myDefaultSearch = other.getDefaultSearch();
    myCustomStateNames = new EnumMap<TaskState, String>(other.getCustomStateNames());
  }

  public Task[] getIssues(@Nullable String request, int max, long since) throws Exception {

    String query = getDefaultSearch();
    if (StringUtil.isNotEmpty(request)) {
      query += " " + request;
    }
    String requestUrl = "/rest/project/issues/?filter=" + encodeUrl(query) + "&max=" + max + "&updatedAfter" + since;
    HttpMethod method = doREST(requestUrl, false);
    InputStream stream = method.getResponseBodyAsStream();

    // todo workaround for http://youtrack.jetbrains.net/issue/JT-7984
    String s = StreamUtil.readText(stream, "UTF-8");
    for (int i = 0; i < s.length(); i++) {
      if (!XMLChar.isValid(s.charAt(i))) {
        s = s.replace(s.charAt(i), ' ');
      }
    }

    Element element;
    try {
      //InputSource source = new InputSource(stream);
      //source.setEncoding("UTF-8");
      //element = new SAXBuilder(false).build(source).getRootElement();
      element = new SAXBuilder(false).build(new StringReader(s)).getRootElement();
    }
    catch (JDOMException e) {
      LOG.error("Can't parse YouTrack response for " + requestUrl, e);
      throw e;
    }
    if ("error".equals(element.getName())) {
      throw new Exception("Error from YouTrack for " + requestUrl + ": '" + element.getText() + "'");
    }

    List<Element> children = element.getChildren("issue");

    final List<Task> tasks = ContainerUtil.mapNotNull(children, new NullableFunction<Element, Task>() {
      public Task fun(Element o) {
        return createIssue(o);
      }
    });
    return tasks.toArray(new Task[tasks.size()]);
  }

  @Nullable
  @Override
  public CancellableConnection createCancellableConnection() {
    PostMethod method = new PostMethod(getUrl() + "/rest/user/login");
    return new HttpTestConnection<PostMethod>(method) {
      @Override
      protected void doTest(PostMethod method) throws Exception {
        login(method);
      }
    };
  }

  private HttpClient login(PostMethod method) throws Exception {
    if (method.getHostConfiguration().getProtocol() == null) {
      throw new Exception("Protocol not specified");
    }
    HttpClient client = getHttpClient();
    client.getState().setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(getUsername(), getPassword()));
    configureHttpMethod(method);
    method.addParameter("login", getUsername());
    method.addParameter("password", getPassword());
    client.getParams().setContentCharset("UTF-8");
    client.executeMethod(method);
    if (method.getStatusCode() != 200) {
      throw new Exception("Cannot login: HTTP status code " + method.getStatusCode());
    }
    String response = method.getResponseBodyAsString(1000);
    if (response == null) {
      throw new NullPointerException();
    }
    if (!response.contains("<login>ok</login>")) {
      int pos = response.indexOf("</error>");
      int length = "<error>".length();
      if (pos > length) {
        response = response.substring(length, pos);
      }
      throw new Exception("Cannot login: " + response);
    }
    return client;
  }

  @Nullable
  public Task findTask(@NotNull String id) throws Exception {
    HttpMethod method = doREST("/rest/issue/byid/" + id, false);
    InputStream stream = method.getResponseBodyAsStream();
    Element element = new SAXBuilder(false).build(stream).getRootElement();
    return element.getName().equals("issue") ? createIssue(element) : null;
  }


  HttpMethod doREST(String request, boolean post) throws Exception {
    HttpClient client = login(new PostMethod(getUrl() + "/rest/user/login"));
    String uri = getUrl() + request;
    HttpMethod method = post ? new PostMethod(uri) : new GetMethod(uri);
    configureHttpMethod(method);
    int status = client.executeMethod(method);
    if (status == 400) {
      InputStream string = method.getResponseBodyAsStream();
      Element element = new SAXBuilder(false).build(string).getRootElement();
      TaskUtil.prettyFormatXmlToLog(LOG, element);
      if ("error".equals(element.getName())) {
        throw new Exception(element.getText());
      }
    }
    return method;
  }

  @Override
  public void setTaskState(@NotNull Task task, @NotNull TaskState state) throws Exception {
    String s = myCustomStateNames.get(state);
    if (StringUtil.isEmpty(s)) {
      s = state.name();
    }
    doREST("/rest/issue/execute/" + task.getId() + "?command=" + encodeUrl("state " + s), true);
  }

  @Nullable
  private Task createIssue(Element element) {
    final String id = element.getAttributeValue("id");
    if (id == null) return null;
    final String summary = element.getAttributeValue("summary");
    if (summary == null) return null;
    final String description = element.getAttributeValue("description");

    String type = element.getAttributeValue("type");
    TaskType taskType = TaskType.OTHER;
    if (type != null) {
      try {
        taskType = TaskType.valueOf(type.toUpperCase());
      }
      catch (IllegalArgumentException e) {
        // do nothing
      }
    }
    final TaskType finalTaskType = taskType;

    final Date updated = new Date(Long.parseLong(element.getAttributeValue("updated")));
    final Date created = new Date(Long.parseLong(element.getAttributeValue("created")));
    final boolean resolved = element.getAttribute("resolved") != null;

    return new Task() {
      @Override
      public boolean isIssue() {
        return true;
      }

      @Override
      public String getIssueUrl() {
        return getUrl() + "/issue/" + getId();
      }

      @NotNull
      @Override
      public String getId() {
        return id;
      }

      @NotNull
      @Override
      public String getSummary() {
        return summary;
      }

      public String getDescription() {
        return description;
      }

      @NotNull
      @Override
      public Comment[] getComments() {
        return Comment.EMPTY_ARRAY;
      }

      @NotNull
      @Override
      public Icon getIcon() {
        return LocalTaskImpl.getIconFromType(getType(), isIssue());
      }

      @NotNull
      @Override
      public TaskType getType() {
        return finalTaskType;
      }

      @Nullable
      @Override
      public Date getUpdated() {
        return updated;
      }

      @Nullable
      @Override
      public Date getCreated() {
        return created;
      }

      @Override
      public boolean isClosed() {
        // IDEA-118605
        return resolved;
      }

      @Override
      public TaskRepository getRepository() {
        return YouTrackRepository.this;
      }
    };
  }

  public String getDefaultSearch() {
    return myDefaultSearch;
  }

  public void setDefaultSearch(String defaultSearch) {
    if (defaultSearch != null) {
      myDefaultSearch = defaultSearch;
    }
  }

  @SuppressWarnings({"EqualsWhichDoesntCheckParameterClass"})
  @Override
  public boolean equals(Object o) {
    if (!super.equals(o)) return false;
    YouTrackRepository repository = (YouTrackRepository)o;
    if (!Comparing.equal(repository.getDefaultSearch(), getDefaultSearch())) return false;
    if (!Comparing.equal(repository.getCustomStateNames(), getCustomStateNames())) return false;
    return true;
  }

  private static final Logger LOG = Logger.getInstance("#com.intellij.tasks.youtrack.YouTrackRepository");

  @Override
  public void updateTimeSpent(@NotNull LocalTask task, @NotNull String timeSpent, @NotNull String comment) throws Exception {
    checkVersion();
    final HttpMethod method = doREST("/rest/issue/execute/" + task.getId() + "?command=work+Today+" + timeSpent.replaceAll(" ", "+") + "+" + comment, true);
    if (method.getStatusCode() != 200) {
      InputStream stream = method.getResponseBodyAsStream();
      String message = new SAXBuilder(false).build(stream).getRootElement().getText();
      throw new Exception(message);
    }
  }

  private void checkVersion() throws Exception {
    HttpMethod method = doREST("/rest/workflow/version", false);
    InputStream stream = method.getResponseBodyAsStream();
    Element element = new SAXBuilder(false).build(stream).getRootElement();
    final boolean timeTrackingAvailable = element.getName().equals("version") && VersionComparatorUtil.compare(element.getChildText("version"), "4.1") >= 0;
    if (!timeTrackingAvailable) {
      throw new Exception("This version of Youtrack the time tracking is not supported");
    }
  }

  @Override
  protected int getFeatures() {
    return super.getFeatures() | TIME_MANAGEMENT | STATE_UPDATING;
  }

  public void setCustomStateNames(Map<TaskState, String> customStateNames) {
    myCustomStateNames.putAll(customStateNames);
  }

  @Tag("customStates")
  @Property(surroundWithTag = false)
  @MapAnnotation(
    surroundWithTag = false,
    keyAttributeName = "state",
    valueAttributeName = "name",
    surroundKeyWithTag = false,
    surroundValueWithTag = false
  )

  public Map<TaskState, String> getCustomStateNames() {
    return myCustomStateNames;
  }

  public void setCustomStateName(TaskState state, String name) {
    myCustomStateNames.put(state, name);
  }
}
