package org.kohsuke.github;

import com.fasterxml.jackson.annotation.JacksonInject;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;

import javax.annotation.Nonnull;

/**
 * The type GHLabel.
 *
 * @author Kohsuke Kawaguchi
 * @see GHIssue#getLabels() GHIssue#getLabels()
 * @see GHRepository#listLabels() GHRepository#listLabels()
 */
public class GHLabel {

    @Nonnull
    private String url, name, color, description;

    @JacksonInject
    private GitHub root;

    GHLabel() {
        url = "";
        name = "";
        color = "";
        description = "";
    }

    /**
     * Gets url.
     *
     * @return the url
     */
    @Nonnull
    public String getUrl() {
        return url;
    }

    /**
     * Gets name.
     *
     * @return the name
     */
    @Nonnull
    public String getName() {
        return name;
    }

    /**
     * Color code without leading '#', such as 'f29513'
     *
     * @return the color
     */
    @Nonnull
    public String getColor() {
        return color;
    }

    /**
     * Purpose of Label
     *
     * @return the description
     */
    @Nonnull
    public String getDescription() {
        return description;
    }

    /**
     * Sets color.
     *
     * @param newColor
     *            6-letter hex color code, like "f29513"
     * @throws IOException
     *             the io exception
     * @deprecated use {@link #set()} instead
     */
    @Deprecated
    public void setColor(String newColor) throws IOException {
        set().color(newColor);
    }

    /**
     * Sets description.
     *
     * @param newDescription
     *            Description of label
     * @throws IOException
     *             the io exception
     * @deprecated use {@link #set()} instead
     */
    @Deprecated
    public void setDescription(String newDescription) throws IOException {
        set().description(newDescription);
    }

    static Collection<String> toNames(Collection<GHLabel> labels) {
        List<String> r = new ArrayList<>();
        for (GHLabel l : labels) {
            r.add(l.getName());
        }
        return r;
    }

    /**
     * Begins the creation of a new instance.
     *
     * Consumer must call {@link Creator#done()} to commit changes.
     *
     * @param repository
     *            the repository in which the label will be created.
     * @return a {@link Creator}
     * @throws IOException
     *             the io exception
     */
    public static Creator create(GHRepository repository) throws IOException {
        return new Creator(repository);
    }

    /**
     * Reads a label from a repository.
     *
     * @param repository
     *            the repository to read from
     * @param name
     *            the name of the label
     * @return a label
     * @throws IOException
     *             the io exception
     */
    public static GHLabel read(@Nonnull GHRepository repository, @Nonnull String name) throws IOException {
        return repository.root.createRequest()
                .withUrlPath(repository.getApiTailUrl("labels"), name)
                .fetch(GHLabel.class);

    }

    /**
     * Reads all labels from a repository.
     *
     * @param repository
     *            the repository to read from
     * @return iterable of all labels
     * @throws IOException
     *             the io exception
     */
    public static PagedIterable<GHLabel> readAll(@Nonnull final GHRepository repository) throws IOException {
        return repository.root.createRequest()
                .withUrlPath(repository.getApiTailUrl("labels"))
                .toIterable(GHLabel[].class, null);

    }

    /**
     * Begins a batch update
     *
     * Consumer must call {@link Updater#done()} to commit changes.
     *
     * @return a {@link Updater}
     */
    public Updater update() {
        return new Updater(this);
    }

    /**
     * Begins a single property update.
     * 
     * @return a {@link Setter}
     */
    public Setter set() {
        return new Setter(this);
    }

    /**
     * Delete this label from this repository. Made static to make it clearer that this deletes the label entirely -
     * different from adding removing labels from objects.
     *
     * @throws IOException
     *             the io exception
     */
    public void delete() throws IOException {
        root.createRequest().method("DELETE").setRawUrlPath(getUrl()).send();
    }

    @Override
    public boolean equals(final Object o) {
        if (this == o)
            return true;
        if (o == null || getClass() != o.getClass())
            return false;
        final GHLabel ghLabel = (GHLabel) o;
        return Objects.equals(url, ghLabel.url) && Objects.equals(name, ghLabel.name)
                && Objects.equals(color, ghLabel.color) && Objects.equals(description, ghLabel.description);
    }

    @Override
    public int hashCode() {
        return Objects.hash(url, name, color, description);
    }

    /**
     * A {@link GHLabelBuilder} that updates a single property per request
     *
     * {@link #done()} is called automatically after the property is set.
     */
    public static class Setter extends GHLabelBuilder<GHLabel> {
        private Setter(@Nonnull GHLabel base) {
            super(GHLabel.class, base.root, base);
            requester.method("PATCH").setRawUrlPath(base.getUrl());
        }
    }

    /**
     * A {@link GHLabelBuilder} that allows multiple properties to be updated per request.
     *
     * Consumer must call {@link #done()} to commit changes.
     */
    public static class Updater extends GHLabelBuilder<Updater> {
        private Updater(@Nonnull GHLabel base) {
            super(Updater.class, base.root, base);
            requester.method("PATCH").setRawUrlPath(base.getUrl());
        }
    }

    /**
     * A {@link GHLabelBuilder} that creates a new {@link GHLabel}
     *
     * Consumer must call {@link #done()} to create the new instance.
     */
    public static class Creator extends GHLabelBuilder<Creator> {
        private Creator(@Nonnull GHRepository repository) {
            super(Creator.class, repository.root, null);
            requester.method("POST").withUrlPath(repository.getApiTailUrl("labels"));
        }
    }

}

@@ -1494,32 +1494,16 @@
      */%0A
-    @Deprecated%0A
     publ
@@ -1549,32 +1549,32 @@
 s IOException %7B%0A
+
         set().co
@@ -1824,24 +1824,8 @@
  */%0A
-    @Deprecated%0A
     
@@ -2489,38 +2489,60 @@
 ion%0A     */%0A    
-public
+@Preview%0A    @Deprecated%0A   
  static Creator 
@@ -2920,31 +2920,24 @@
      */%0A    
-public 
 static GHLab
@@ -3424,31 +3424,24 @@
      */%0A    
-public 
 static Paged
@@ -3851,32 +3851,61 @@
 pdater%7D%0A     */%0A
+    @Preview%0A    @Deprecated%0A
     public Updat
@@ -4047,32 +4047,61 @@
 Setter%7D%0A     */%0A
+    @Preview%0A    @Deprecated%0A
     public Sette
@@ -5248,32 +5248,61 @@
 is set.%0A     */%0A
+    @Preview%0A    @Deprecated%0A
     public stati
@@ -5701,32 +5701,61 @@
 hanges.%0A     */%0A
+    @Preview%0A    @Deprecated%0A
     public stati
@@ -6141,24 +6141,24 @@
 stance.%0A
-
      */%0A
     publ
@@ -6141,32 +6141,61 @@
 stance.%0A     */%0A
+    @Preview%0A    @Deprecated%0A
     public stati

Change to Preview for new builder pattern