package com.codahale.metrics.jenkins.graphite;

import com.codahale.metrics.graphite.Graphite;
import hudson.Extension;
import hudson.model.AbstractDescribableImpl;
import hudson.model.Descriptor;
import jenkins.model.Jenkins;
import net.sf.json.JSONObject;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.StaplerRequest;

import javax.annotation.concurrent.GuardedBy;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * @author Stephen Connolly
 */
public class GraphiteServer extends AbstractDescribableImpl<GraphiteServer> {

    private static final Logger LOGGER = Logger.getLogger(GraphiteServer.class.getName());
    private final String hostname;

    private final int port;

    private final String prefix;

    @DataBoundConstructor
    public GraphiteServer(String hostname, int port, String prefix) {
        this.hostname = hostname;
        this.port = port;
        this.prefix = prefix;
    }

    public String getHostname() {
        return hostname;
    }

    public int getPort() {
        return port;
    }

    public String getPrefix() {
        return prefix;
    }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder("GraphiteServer{");
        sb.append("hostname='").append(hostname).append('\'');
        sb.append(", port=").append(port);
        sb.append(", prefix='").append(prefix).append('\'');
        sb.append('}');
        return sb.toString();
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }

        GraphiteServer that = (GraphiteServer) o;

        if (port != that.port) {
            return false;
        }
        if (hostname != null ? !hostname.equals(that.hostname) : that.hostname != null) {
            return false;
        }
        if (prefix != null ? !prefix.equals(that.prefix) : that.prefix != null) {
            return false;
        }

        return true;
    }

    @Override
    public int hashCode() {
        int result = hostname != null ? hostname.hashCode() : 0;
        result = 31 * result + port;
        result = 31 * result + (prefix != null ? prefix.hashCode() : 0);
        return result;
    }

    @Extension
    public static class DescriptorImpl extends Descriptor<GraphiteServer> {
        @GuardedBy("this")
        private List<GraphiteServer> servers;

        @Override
        public String getDisplayName() {
            return Messages.GraphiteServer_displayName();
        }

        public DescriptorImpl() {
            super();
            load();
        }

        @Override
        public synchronized boolean configure(StaplerRequest req, JSONObject json) throws FormException {
            servers = req.bindJSONToList(GraphiteServer.class, json.get("servers"));
            save();
            try {
                Jenkins.getInstance().getPlugin(PluginImpl.class).updateReporters();
            } catch (URISyntaxException e) {
                LOGGER.log(Level.WARNING, "Could not update Graphite reporters", e);
            }
            return true;
        }

        public synchronized List<GraphiteServer> getServers() {
            return servers == null
                    ? Collections.<GraphiteServer>emptyList()
                    : Collections.unmodifiableList(new ArrayList<GraphiteServer>(servers));
        }
    }

}

@@ -2854,29 +2854,16 @@
  public 
-synchronized 
 boolean 
@@ -2950,16 +2950,17 @@
   se
+tSe
 rvers
- = 
+(
 req.
@@ -3016,16 +3016,17 @@
 rvers%22))
+)
 ;%0A      
@@ -3035,33 +3035,20 @@
     
-save();%0A            try %7B
+return true;
 %0A   
@@ -3052,24 +3052,27 @@
         
+%7D%0A%0A
         
 Jenkins.
@@ -3067,76 +3067,63 @@
     
-Jenkins.getInstance().getPlugin(PluginImpl.class).updateReport
+public synchronized List%3CGraphiteServer%3E getServ
 ers()
-;
+ %7B
 %0A   
@@ -3135,125 +3135,92 @@
     
-%7D catch (URISyntaxException e) %7B%0A                LOGGER.log(Level.WARNING, %22Could not update Graphite reporters%22, e);
+return servers == null%0A                    ? Collections.%3CGraphiteServer%3EemptyList()
 %0A   
@@ -3228,26 +3228,24 @@
         
-%7D%0A
         
     retu
@@ -3232,39 +3232,94 @@
             
-    return true
+: Collections.unmodifiableList(new ArrayList%3CGraphiteServer%3E(servers))
 ;%0A        %7D%0A
@@ -3339,32 +3339,48 @@
 ic synchronized 
+void setServers(
 List%3CGraphiteSer
@@ -3380,35 +3380,31 @@
 hiteServer%3E 
-getS
+s
 ervers
-(
 ) %7B%0A        
@@ -3407,38 +3407,59 @@
         
-return servers == null
+this.servers = servers;%0A            save();
 %0A       
@@ -3459,32 +3459,38 @@
             
+try %7B%0A
         
 ? Collection
@@ -3481,49 +3481,84 @@
     
-? Collections.%3CGraphiteServer%3EemptyList
+        Jenkins.getInstance().getPlugin(PluginImpl.class).updateReporters
 ()
+;
 %0A   
@@ -3570,87 +3570,139 @@
     
-        : Collections.unmodifiableList(new ArrayList%3CGraphiteServer%3E(servers));
+%7D catch (URISyntaxException e) %7B%0A                LOGGER.log(Level.WARNING, %22Could not update Graphite reporters%22, e);%0A            %7D
 %0A   

Allow setting graphite server by code