package com.intellij.tasks;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

/**
 * @author Mikhail Golubev
 */
public class CustomTaskState {
  private String myId;
  private String myPresentableName;
  private boolean myPredefined;

  /**
   * For serialization purposes only.
   */
  public CustomTaskState() {
  }

  public CustomTaskState(@NotNull String id, @NotNull String name) {
    myId = id;
    myPresentableName = name;
  }

  @NotNull
  public String getId() {
    return myId;
  }

  /**
   * For serialization purposes only.
   */
  public void setId(String id) {
    myId = id;
  }

  @NotNull
  public String getPresentableName() {
    return myPresentableName;
  }

  /**
   * For serialization purposes only.
   */
  public void setPresentableName(@NotNull String name) {
    myPresentableName = name;
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) return true;
    if (!(o instanceof CustomTaskState)) return false;

    final CustomTaskState state = (CustomTaskState)o;

    return myId.equals(state.myId);
  }

  @Override
  public int hashCode() {
    return myId.hashCode();
  }

  @NotNull
  public static CustomTaskState fromPredefined(@NotNull TaskState state) {
    final CustomTaskState result = new CustomTaskState(state.name(), state.getPresentableName());
    result.setPredefined(true);
    return result;
  }

  @Nullable
  public TaskState asPredefined() {
    if (isPredefined()) {
      try {
        return TaskState.valueOf(getId());
      }
      catch (IllegalArgumentException ignored) {
      }
    }
    return null;
  }

  private boolean isPredefined() {
    return myPredefined;
  }

  /**
   * For serialization purposes only.
   */
  public void setPredefined(boolean predefined) {
    myPredefined = predefined;
  }

  @Override
  public String toString() {
    return "CustomTaskState(id='" + myId + '\'' + ", name='" + myPresentableName + '\'' + ", myPredefined=" + myPredefined + ')';
  }
}

@@ -465,24 +465,279 @@
  name;%0A  %7D%0A%0A
+  /**%0A   * Unique ID (e.g. number or unique name) of this state that can be used later to update state of an issue%0A   * in %7B@link TaskRepository#setTaskState(Task, CustomTaskState)%7D.%0A   *%0A   * @see TaskRepository#setTaskState(Task, CustomTaskState)%0A   */%0A
   @NotNull%0A 
@@ -882,24 +882,145 @@
  = id;%0A  %7D%0A%0A
+  /**%0A   * Text that describes this state and will be shown to user in UI (unlike ID it's not necessarily unique).%0A   */%0A
   @NotNull%0A 
@@ -1543,467 +1543,1672 @@
 %0A%0A  
-@NotNull%0A  public static CustomTaskState fromPredefined(@NotNull TaskState state) %7B%0A    final CustomTaskState result = new CustomTaskState(state.name(), state.getPresentableName());%0A    result.setPredefined(true);%0A    return result;%0A  %7D%0A%0A  @Nullable%0A  public TaskState asPredefined() %7B%0A    if (isPredefined()) %7B%0A      try %7B%0A        return TaskState.valueOf(getId());%0A      %7D%0A      catch (IllegalArgumentException ignored) %7B%0A      %7D%0A    %7D%0A    return null;%0A  %7D%0A
+/**%0A   * Creates custom state for which ID is identical to %7B@link TaskState#name%7D of the given predefined state and %7B@link #isPredefined()%7D%0A   * returns true. If your repository provides only fixed set of available states, that are one of those described in %7B@link TaskState%7D,%0A   * you may find this methods useful to implement %7B@link TaskRepository#getAvailableTaskStates(Task)%7D.%0A   *%0A   * @return custom task state that represents given predefined state%0A   * @see #asPredefined()%0A   * @see #isPredefined()%0A   * @see TaskRepository#getAvailableTaskStates(Task)%0A   */%0A  @NotNull%0A  public static CustomTaskState fromPredefined(@NotNull TaskState state) %7B%0A    final CustomTaskState result = new CustomTaskState(state.name(), state.getPresentableName());%0A    result.setPredefined(true);%0A    return result;%0A  %7D%0A%0A  /**%0A   * Returns corresponding value of %7B@link TaskState%7D that has the same name as ID of this state.%0A   * It's intended to be used for custom states created using %7B@link #fromPredefined%7D.%0A   *%0A   * @return predefined task state as described or %7B@code null%7D if such state doesn't exists or %7B@link #isPredefined()%7D returns false%0A   * @see #isPredefined()%0A   */%0A  @Nullable%0A  public TaskState asPredefined() %7B%0A    if (isPredefined()) %7B%0A      try %7B%0A        return TaskState.valueOf(getId());%0A      %7D%0A      catch (IllegalArgumentException ignored) %7B%0A      %7D%0A    %7D%0A    return null;%0A  %7D%0A%0A  /**%0A   * Means that this custom state can be directly mapped to legacy %7B@link TaskState%7D. If it's false, %7B@link #asPredefined()%7D returns %7B@code null%7D.%0A   * It's intended to be used mainly for compatibility with existing repositories.%0A   *%0A   * @see #asPredefined()%0A   */
 %0A  p
@@ -3539,19 +3539,17 @@
 '' + %22, 
-myP
+p
 redefine

Update javadoc and toString for CustomTaskState