/*
 * The MIT License
 *
 * Copyright (c) 2010, Kohsuke Kawaguchi
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package org.kohsuke.github;

import org.apache.commons.io.IOUtils;

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import static org.kohsuke.github.GitHub.MAPPER;

/**
 * Handles HTTP POST.
 * @author Kohsuke Kawaguchi
 */
class Poster {
    private final GitHub root;
    private final Map<String,String> args = new HashMap<String, String>();
    private boolean authenticate;

    Poster(GitHub root) {
        this.root = root;
    }

    public Poster withCredential() {
        root.requireCredential();
        authenticate = true;
        return this;
    }

    public Poster with(String key, int value) {
        return with(key,String.valueOf(value));
    }

    public Poster with(String key, String value) {
        if (value!=null)
            this.args.put(key,value);
        return this;
    }

    public void to(URL url) throws IOException {
        to(url,null);
    }

    /**
     * POSTs the form to the specified URL.
     *
     * @throws IOException
     *      if the server returns 4xx/5xx responses.
     * @return
     *      {@link Reader} that reads the response.
     */
    public <T> T to(URL url, Class<T> type) throws IOException {
        return to(url,type,"POST");
    }

    public <T> T to(URL url, Class<T> type, String method) throws IOException {
        HttpURLConnection uc = (HttpURLConnection) url.openConnection();

        uc.setDoOutput(true);
        uc.setRequestProperty("Content-type","application/x-www-form-urlencoded");
        if (authenticate)
            uc.setRequestProperty("Authorization", "Basic " + root.encodedAuthorization);
        uc.setRequestMethod(method);


        StringBuilder body = new StringBuilder();
        for (Entry<String, String> e : args.entrySet()) {
            if (body.length()>0)    body.append('&');
            body.append(URLEncoder.encode(e.getKey(),"UTF-8"));
            body.append('=');
            body.append(URLEncoder.encode(e.getValue(),"UTF-8"));
        }

        OutputStreamWriter o = new OutputStreamWriter(uc.getOutputStream(), "UTF-8");
        o.write(body.toString());
        o.close();


        try {
            InputStreamReader r = new InputStreamReader(uc.getInputStream(), "UTF-8");
            if (type==null) {
                String data = IOUtils.toString(r);
                return null;
            }
            return MAPPER.readValue(r,type);
        } catch (IOException e) {
            throw (IOException)new IOException(IOUtils.toString(uc.getErrorStream(),"UTF-8")).initCause(e);
        }
    }
}

@@ -1318,32 +1318,77 @@
 java.io.Reader;%0A
+import java.io.UnsupportedEncodingException;%0A
 import java.net.
@@ -1472,23 +1472,25 @@
 va.util.
-HashMap
+ArrayList
 ;%0Aimport
@@ -1504,39 +1504,12 @@
 til.
-Map;%0Aimport java.util.Map.Entry
+List
 ;%0A%0Ai
@@ -1547,22 +1547,17 @@
 .GitHub.
-MAPPER
+*
 ;%0A%0A/**%0A 
@@ -1674,27 +1674,21 @@
 e final 
-Map%3CString,
+List%3C
 String%3E 
@@ -1702,24 +1702,18 @@
 new 
-HashMap%3CString, 
+ArrayList%3C
 Stri
@@ -2119,16 +2119,18 @@
 e!=null)
+ %7B
 %0A       
@@ -2139,32 +2139,236 @@
    t
-his.args.put(key,value);
+ry %7B%0A                args.add(URLEncoder.encode(key,%22UTF-8%22)+'='+URLEncoder.encode(value,%22UTF-8%22));%0A            %7D catch (UnsupportedEncodingException e) %7B%0A                throw new Error(e); // impossible%0A            %7D%0A        %7D
 %0A   
@@ -3281,49 +3281,23 @@
 or (
-Entry%3CString, String%3E e : args.entrySet()
+String e : args
 ) %7B%0A
@@ -3378,141 +3378,9 @@
 end(
-URLEncoder.encode(e.getKey(),%22UTF-8%22));%0A            body.append('=');%0A            body.append(URLEncoder.encode(e.getValue(),%22UTF-8%22)
+e
 );%0A 

support multiple values for the same key.