package org.apache.maven.jira;

/* ====================================================================
 *   Copyright 2001-2004 The Apache Software Foundation.
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 * ====================================================================
 */

import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HostConfiguration;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpState;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.StatusLine;
import org.apache.commons.httpclient.UsernamePasswordCredentials;
import org.apache.commons.httpclient.methods.GetMethod;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.apache.maven.jelly.MavenJellyContext;
import org.apache.maven.project.Project;

import java.io.File;
import java.io.FileWriter;
import java.io.PrintWriter;

public class JiraDownloader
{
    /**
     * Log for debug output
     */
    private static Log LOG = LogFactory.getLog(JiraDownloader.class);
    
    /** Output file for xml document */
    private File output;
    
    /** Number of entries max */
    private int nbEntriesMax;
    
    private Project project;
    
    /**
     * Set the output file for the log.
     * @param output the output file
     */
    public void setOutput(File output)
    {
        this.output = output;
    }
    
    /**
     * @return Project
     */
    public Object getProject()
    {
        return project;
    }

    /**
     * Sets the project.
     * @param project The project to set
     */
    public void setProject(Object project)
    {
        //System.out.println("Setting project: " + project);
        this.project = (Project) project;
    }
    
    /**
     * Sets the number of entries.
     * @param nbEntries The number of entries
     */
    public void setNbEntries(int nbEntries)
    {
        nbEntriesMax = nbEntries;
    }
    
    public void doExecute() throws Exception
    {
        MavenJellyContext ctx;
        String proxyHost;
        String proxyPort;
        String proxyUser;
        String proxyPass;
        String link;
        
        if (getProject() == null)
        {
            throw new Exception("No project set.");
        }
        else
        {
            if (((Project) getProject()).getIssueTrackingUrl() == null)
            {
                throw new Exception("No issue tracking url set.");
            }
            else
            {
                String url = ((Project) getProject()).getIssueTrackingUrl();
                int pos = url.indexOf("?");
                String id = url.substring(pos+4);
                url = url.substring(0, url.lastIndexOf("/"));
                link = url + "/secure/IssueNavigator.jspa?view=rss&pid=" + id + "&sorter/field=issuekey&sorter/order=DESC&sorter/field=status&sorter/order=DESC&tempMax=" + String.valueOf(nbEntriesMax) + "&reset=true";
            }
        }
        
        ctx = ((Project) getProject()).getContext();
        
        proxyHost = ctx.getProxyHost();
        proxyPort = ctx.getProxyPort();
        proxyUser = ctx.getProxyUserName();
        proxyPass = ctx.getProxyPassword();
        
        try
        {
            HttpClient cl = new HttpClient();
            HostConfiguration hc = new HostConfiguration();

            if (proxyHost != null)
            {
                hc.setProxy(proxyHost, Integer.parseInt(proxyPort));
            }
            HttpState state = new HttpState();

            if (proxyUser != null && proxyPass != null)
            {
                state.setProxyCredentials(null, null, new UsernamePasswordCredentials(proxyUser, proxyPass));
            }

            cl.setHostConfiguration(hc);
            cl.setState(state);
            
            // execute the GET
            GetMethod gm = download(cl, link);
            StatusLine sl = gm.getStatusLine();
            
            if (sl == null) {
                LOG.info("Unknown error validating link : " + link);
                return;
            }
            
            if (gm.getStatusCode() == HttpStatus.SC_MOVED_TEMPORARILY)
            {
                Header locationHeader = gm.getResponseHeader("Location");
                if (locationHeader == null)  {
                    LOG.info("Site sent redirect, but did not set Location header");
                } else  {
                    String newLink = locationHeader.getValue();
                    LOG.debug("Following 1 redirect to " + newLink);
                    gm = download(cl, newLink);
                }
            }

            if (gm.getStatusCode() != HttpStatus.SC_OK)
            {
                String msg = "Received: [" + gm.getStatusCode() + "] for " + link;
                LOG.info(msg);
                System.out.println(msg);
            }

        }
        catch (Exception e)
        {
            LOG.warn("Error accessing " + link);
            e.printStackTrace();
        }
    }
    
    private GetMethod download(HttpClient cl, String link)
    {   
        GetMethod gm = new GetMethod(link);
        try
        {
            System.out.println("Downloading " + link);
            gm.setFollowRedirects(true);
            cl.executeMethod(gm);
            final String strGetResponseBody = gm.getResponseBodyAsString();
            PrintWriter pw = new PrintWriter(new FileWriter(output));
            pw.print(strGetResponseBody);
            pw.close();
        }
        catch (Exception e)
        {
            System.out.println("Error downloading " + link);
        }
        return gm;
    }
}
