/**
 *  @(#)RangeContribs.java 0.01 15/10/2012
 *  Copyright (C) 2012 - 2013 MER-C
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.

 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.wikipedia.servlets;

import java.io.*;
import java.util.*;
import javax.swing.JOptionPane;
import javax.servlet.*;
import javax.servlet.http.*;
import org.wikipedia.*;

/**
 *  Fetches contributions from an IP address range or a group of users that
 *  have a common prefix.
 *  @author MER-C
 *  @version 0.01
 */
public class PrefixContribs extends HttpServlet
{
    private static final Wiki enWiki = new Wiki("en.wikipedia.org");
    
    /**
     *  Initialize all Wiki objects.
     */
    static
    {
        enWiki.setMaxLag(-1);
    }
    
    /**
     *  This servlet is intended to run on Google App Engine, see { @link
     *  https://cloud.google.com/appengine/docs/quotas here } and { @link
     *  https://cloud.google.com/appengine/docs/java#Java_The_sandbox here }
     *  for what you can and cannot do in this environment. 
     *  <p>
     *  This servlet runs at https://wikipediatools.appspot.com/prefixcontribs.jsp .
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    {
        if (ServletUtils.checkBlacklist(request, response))
            return;
        response.setContentType("text/html; charset=UTF-8");
        PrintWriter out = response.getWriter();
        StringBuilder buffer = new StringBuilder(50000);
        
        // header
        buffer.append(ServletUtils.generateHead("Prefix contributions", null));
        buffer.append("<p>This tool retrieves contributions of an IP ");
        buffer.append("range or username prefix for the last 7 days. To search for an IP\n");
        buffer.append("range, use a search key of (say) 111.222. for 111.222.0.0/16. /24s ");
        buffer.append("and IPv6 addresses work similarly.\nNo sanitization is performed on ");
        buffer.append("IP addresses.\n\n");
        
        // form
        buffer.append("<form action=\"./prefixcontribs.jsp\" method=GET>\n<p>Search string: ");
        buffer.append("<input type=text name=prefix");
        String prefix = request.getParameter("prefix");
        if (prefix != null)
        {
            buffer.append(" value=\"");
            buffer.append(ServletUtils.sanitize(prefix));
            buffer.append("\">\n");
        }
        else
            buffer.append(">\n");
        buffer.append("<input type=submit value=\"Search\"></form>\n\n");
        
        if (prefix != null)
        {
            if (prefix.length() < 4)
                buffer.append("Error: search key of insufficient length.\n");
            else
            {
                Calendar cutoff = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
                cutoff.add(Calendar.DAY_OF_MONTH, -7);
                Wiki.Revision[] revisions = enWiki.contribs("", prefix, cutoff, null);
                if (revisions.length == 0)
                    buffer.append("No contributions found.");
                else
                    buffer.append(ParserUtils.revisionsToHTML(enWiki, revisions));
            }
        }
        
        // footer
        buffer.append("<br><br>");
        buffer.append(ServletUtils.generateFooter("Prefix contributions"));
        out.write(buffer.toString());
        out.close();
    }
    
    /**
     *  Main for testing/offline stuff. Pipe the output to a HTML file.
     *  @param args the command line arguments (none expected)
     *  @throws IOException if a network error occurs
     */
    public static void main(String[] args) throws IOException
    {
        String prefix = JOptionPane.showInputDialog(null, "Enter query string");
        if (prefix == null)
            System.exit(0);
        Calendar cutoff = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
        cutoff.add(Calendar.DAY_OF_MONTH, -7);
        Wiki.Revision[] revisions = enWiki.contribs("", prefix, cutoff, null);
        if (revisions.length == 0)
            System.out.println("No contributions found.");
        else
            System.out.println(ParserUtils.revisionsToHTML(enWiki, revisions));
    }
}

@@ -2803,24 +2803,76 @@
 dresses.
+ Timeouts are more likely for the longer time spans.
 %5Cn%5Cn%22);%0A
         
@@ -2855,32 +2855,32 @@
 e spans.%5Cn%5Cn%22);%0A
-
         %0A       
@@ -3340,32 +3340,510 @@
 buffer.append(%22%3C
+p%3EFor last: %22);%0A        String time = request.getParameter(%22time%22);%0A        if (time == null)%0A            time = %227%22;%0A        LinkedHashMap%3CString, String%3E options = new LinkedHashMap%3C%3E(10);%0A%09options.put(%221%22, %221 day%22);%0A        options.put(%223%22, %223 days%22);%0A        options.put(%227%22, %227 days%22);%0A        options.put(%2214%22, %2214 days%22);%0A        options.put(%2230%22, %2230 days%22);%0A        buffer.append(ServletUtils.generateComboBox(%22time%22, options, time, false));%0A        buffer.append(%22%3Cp%3E%3C
 input type=submi
@@ -4198,33 +4198,56 @@
 .DAY_OF_MONTH, -
-7
+1*Integer.parseInt(time)
 );%0A             

Add time combo box. Closes #101.