package org.apache.maven.plugin.jira;

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.MappingJsonFactory;
import org.apache.cxf.configuration.security.AuthorizationPolicy;
import org.apache.cxf.configuration.security.ProxyAuthorizationPolicy;
import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.interceptor.LoggingOutInterceptor;
import org.apache.cxf.jaxrs.client.ClientConfiguration;
import org.apache.cxf.jaxrs.client.WebClient;
import org.apache.cxf.message.Message;
import org.apache.cxf.transport.http.HTTPConduit;
import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;
import org.apache.cxf.transports.http.configuration.ProxyServerType;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugin.issues.Issue;

import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * Use the JIRA REST API to implement the download.
 *
 * This class assumes that the URL points to a copy of JIRA that implements the REST API.
 * A static function may be forthcoming in here to probe and see if a given URL supports it.
 *
 */
public class RestJiraDownloader extends AbstractJiraDownloader
{
    private List<Issue> issueList;
    private JsonFactory jsonFactory;
    private SimpleDateFormat dateFormat;

    private List<String> resolvedFixVersionIds;
    private List<String> resolvedStatusIds;
    private List<String> resolvedComponentIds;
    private List<String> resolvedTypeIds;
    private List<String> resolvedResolutionIds;
    private List<String> resolvedPriorityIds;

    private String jiraProject;

    public static class NoRest extends Exception
    {
        public NoRest( )
        {
            // blank on purpose.
        }
        public NoRest( String message )
        {
            super( message );
        }
    }

    public RestJiraDownloader()
    {
        jsonFactory = new MappingJsonFactory(  );
        //2012-07-17T06:26:47.723-0500
        dateFormat = new SimpleDateFormat( "yyyy-MM-dd'T'HH:mm:ss.SSSZ" );
        resolvedFixVersionIds = new ArrayList<String>(  );
        resolvedStatusIds = new ArrayList<String>(  );
        resolvedComponentIds = new ArrayList<String>(  );
        resolvedTypeIds = new ArrayList<String>(  );
        resolvedResolutionIds = new ArrayList<String>(  );
        resolvedPriorityIds = new ArrayList<String>(  );
    }

    public void doExecute()
        throws Exception
    {

        Map<String, String> urlMap = JiraHelper.getJiraUrlAndProjectName( project.getIssueManagement().getUrl() );
        String jiraUrl = urlMap.get( "url" );
        jiraProject = urlMap.get( "project" );

        // This classloader juggling is a workaround for a classic Maven 2 class loader management bug.
        ClassLoader ccl = Thread.currentThread().getContextClassLoader();
        try
        {
            Thread.currentThread().setContextClassLoader( WebClient.class.getClassLoader( ) );
            WebClient client = setupWebClient( jiraUrl );

            // We use version 2 of the REST API, that first appeared in JIRA 5
            // Check if version 2 of the REST API is supported
            // http://docs.atlassian.com/jira/REST/5.0/
            // Note that serverInfo can always be accessed without authentication
            client.replacePath( "/rest/api/2/serverInfo" );
            client.accept( MediaType.APPLICATION_JSON );
            Response siResponse = client.get();
            if ( siResponse.getStatus() != Response.Status.OK.getStatusCode() )
            {
                throw new NoRest(
                    "This JIRA server does not support version 2 of the REST API, which maven-changes-plugin requires." );
            }

            doSessionAuth( client );

            resolveIds( client, jiraProject );

            String jqlQuery = new JqlQueryBuilder( log ).urlEncode( false ).project( jiraProject ).fixVersion(
                getFixFor() ).fixVersionIds( resolvedFixVersionIds ).statusIds( resolvedStatusIds ).priorityIds(
                resolvedPriorityIds ).resolutionIds( resolvedResolutionIds ).components( resolvedComponentIds ).typeIds(
                resolvedTypeIds ).sortColumnNames( sortColumnNames ).build();

            StringWriter searchParamStringWriter = new StringWriter();
            JsonGenerator gen = jsonFactory.createGenerator( searchParamStringWriter );
            gen.writeStartObject();
            gen.writeStringField( "jql", jqlQuery );
            gen.writeNumberField( "maxResults", nbEntriesMax );
            gen.writeArrayFieldStart( "fields" );
            // Retrieve all fields. If that seems slow, we can reconsider.
            gen.writeString( "*all" );
            gen.writeEndArray();
            gen.writeEndObject();
            gen.close();
            client.replacePath( "/rest/api/2/search" );
            client.type( MediaType.APPLICATION_JSON_TYPE );
            client.accept( MediaType.APPLICATION_JSON_TYPE );
            Response searchResponse = client.post( searchParamStringWriter.toString() );
            if ( searchResponse.getStatus() != Response.Status.OK.getStatusCode() )
            {
                reportErrors( searchResponse );
            }

            JsonNode issueTree = getResponseTree( searchResponse );
            assert issueTree.isObject();
            JsonNode issuesNode = issueTree.get( "issues" );
            assert issuesNode.isArray();
            buildIssues( issuesNode, jiraUrl, jiraProject );
        }
        finally
        {
            Thread.currentThread().setContextClassLoader( ccl );
        }
    }

    private JsonNode getResponseTree( Response response )
        throws IOException
    {
        JsonParser jsonParser = jsonFactory.createJsonParser( (InputStream) response.getEntity() );
        return (JsonNode) jsonParser.readValueAsTree();
    }

    private void reportErrors( Response resp )
        throws IOException, MojoExecutionException
    {
        if ( MediaType.APPLICATION_JSON_TYPE.getType().equals( getResponseMediaType( resp ).getType() ) )
        {
            JsonNode errorTree = getResponseTree( resp );
            assert errorTree.isObject();
            JsonNode messages = errorTree.get( "errorMessages" );
            if ( messages != null )
            {
                for ( int mx = 0; mx < messages.size(); mx ++ )
                {
                    getLog().error( messages.get( mx ).asText() );
                }
            }
            else
            {
                JsonNode message = errorTree.get( "message" );
                if ( message != null )
                {
                    getLog().error( message.asText() );
                }
            }
        }
        throw new MojoExecutionException( String.format( "Failed to query issues; response %d", resp.getStatus() ) );
    }

    private void resolveIds( WebClient client, String jiraProject )
        throws IOException, MojoExecutionException, MojoFailureException
    {
        resolveList( resolvedComponentIds, client, "components",  component, "/rest/api/2/project/{key}/components",
                     jiraProject );
        resolveList( resolvedFixVersionIds, client, "fixVersions", fixVersionIds, "/rest/api/2/project/{key}/versions",
                     jiraProject );
        resolveList( resolvedStatusIds, client, "status", statusIds, "/rest/api/2/status" );
        resolveList( resolvedResolutionIds, client, "resolution", resolutionIds, "/rest/api/2/resolution" );
        resolveList( resolvedTypeIds, client, "type", typeIds, "/rest/api/2/issuetype" );
        resolveList( resolvedPriorityIds, client, "priority", priorityIds, "/rest/api/2/priority" );
    }

    private void resolveList( List<String> targetList, WebClient client, String what, String input,
                              String listRestUrlPattern, String... listUrlArgs )
        throws IOException, MojoExecutionException, MojoFailureException
    {
        if ( input == null || input.length() == 0 )
        {
            return;
        }
        if ( listUrlArgs != null && listUrlArgs.length != 0 )
        {
            client.replacePath( "/" );
            client.path( listRestUrlPattern, listUrlArgs );
        }
        else
        {
            client.replacePath( listRestUrlPattern );
        }
        client.accept( MediaType.APPLICATION_JSON );
        Response resp = client.get();
        if ( resp.getStatus() != 200 )
        {
            getLog().error( String.format( "Could not get %s list from %s", what, listRestUrlPattern ) );
            reportErrors( resp );
        }

        JsonNode items = getResponseTree( resp );
        String[] pieces = input.split( "," );
        for ( String item : pieces )
        {
            targetList.add( resolveOneItem( items, what, item ) );
        }
    }

    private String resolveOneItem( JsonNode items, String what, String nameOrId )
        throws IOException, MojoExecutionException, MojoFailureException
    {
        for ( int cx = 0; cx < items.size(); cx ++ )
        {
            JsonNode item = items.get( cx );
            if ( nameOrId.equals( item.get( "id" ).asText() ) )
            {
                return nameOrId;
            }
            else if ( nameOrId.equals( item.get( "name" ).asText() ) )
            {
                return item.get( "id" ).asText();
            }
        }
        throw new MojoFailureException( String.format( "Could not find %s %s.", what, nameOrId ) );
    }

    private MediaType getResponseMediaType( Response response )
    {
        String header = (String) response.getMetadata().getFirst( HttpHeaders.CONTENT_TYPE ) ;
        return header == null ? null : MediaType.valueOf( header );
    }

    private void buildIssues( JsonNode issuesNode, String jiraUrl, String jiraProject )
    {
        issueList = new ArrayList<Issue>(  );
        for ( int ix = 0; ix < issuesNode.size(); ix++ )
        {
            JsonNode issueNode = issuesNode.get( ix );
            assert issueNode.isObject();
            Issue issue = new Issue();
            JsonNode val;

            val = issueNode.get( "id" );
            if ( val != null )
            {
                issue.setId( val.asText() );
            }

            val = issueNode.get( "key" );
            if ( val != null )
            {
                issue.setKey( val.asText() );
                issue.setLink( String.format( "%s/browse/%s", jiraUrl, val.asText() ) );
            }

            // much of what we want is in here.
            JsonNode fieldsNode = issueNode.get( "fields" );

            val = fieldsNode.get( "assignee" );
            processAssignee( issue, val );

            val = fieldsNode.get( "created" );
            processCreated( issue, val );

            val = fieldsNode.get( "comment" );
            processComments( issue, val );

            val = fieldsNode.get( "components" );
            processComponents( issue, val );

            val = fieldsNode.get( "fixVersions" );
            processFixVersions( issue, val );

            val = fieldsNode.get( "issuetype" );
            processIssueType( issue, val );

            val = fieldsNode.get( "priority" );
            processPriority( issue, val );

            val = fieldsNode.get( "reporter" );
            processReporter( issue, val );

            val = fieldsNode.get( "resolution" );
            processResolution( issue, val );

            val = fieldsNode.get( "status" );
            processStatus( issue, val );

            val = fieldsNode.get( "summary" );
            if ( val != null )
            {
                issue.setSummary( val.asText() );
            }

            val = fieldsNode.get( "title" );
            if ( val != null )
            {
                issue.setTitle( val.asText() );
            }

            val = fieldsNode.get( "updated" );
            processUpdated( issue, val );

            val = fieldsNode.get( "versions" );
            processVersions( issue, val );

            issueList.add( issue );
        }
    }

    private void processVersions( Issue issue, JsonNode val )
    {
        StringBuilder sb = new StringBuilder( );
        if ( val != null )
        {
            for ( int vx = 0; vx < val.size(); vx ++ )
            {
                sb.append( val.get( vx ).get( "name" ).asText() );
                sb.append( ", " );
            }
        }
        if ( sb.length() > 0 )
        {
            // remove last ", "
            issue.setVersion( sb.substring( 0, sb.length() - 2 ) );
        }
    }

    private void processStatus( Issue issue, JsonNode val )
    {
        if ( val != null )
        {
            issue.setStatus( val.get( "name" ).asText() );
        }
    }

    private void processPriority( Issue issue, JsonNode val )
    {
        if ( val != null )
        {
            issue.setPriority( val.get( "name" ).asText() );
        }
    }

    private void processResolution( Issue issue, JsonNode val )
    {
        if ( val != null )
        {
            issue.setResolution( val.get( "name" ).asText() );
        }
    }

    private String getPerson( JsonNode val )
    {
        JsonNode nameNode = val.get( "displayName" );
        if ( nameNode == null )
        {
            nameNode = val.get( "name" );
        }
        if ( nameNode != null )
        {
            return nameNode.asText();
        }
        else
        {
            return null;
        }
    }

    private void processAssignee( Issue issue, JsonNode val )
    {
        if ( val != null )
        {
            String text = getPerson( val );
            if ( text != null )
            {
                issue.setAssignee( text );
            }
        }
    }

    private void processReporter( Issue issue, JsonNode val )
    {
        if ( val != null )
        {
            String text = getPerson( val );
            if ( text != null )
            {
                issue.setReporter( text );
            }
        }
    }

    private void processCreated( Issue issue, JsonNode val )
    {
        if ( val != null )
        {
            try
            {
                issue.setCreated( parseDate( val ) );
            }
            catch ( ParseException e )
            {
                getLog().warn( "Invalid created date " + val.asText() );
            }
        }
    }

    private void processUpdated( Issue issue, JsonNode val )
    {
        if ( val != null )
        {
            try
            {
                issue.setUpdated( parseDate( val ) );
            }
            catch ( ParseException e )
            {
                getLog().warn( "Invalid updated date " + val.asText() );
            }
        }
    }

    private Date parseDate( JsonNode val )
        throws ParseException
    {
        return dateFormat.parse( val.asText() );
    }

    private void processFixVersions( Issue issue, JsonNode val )
    {
        if ( val != null )
        {
            assert val.isArray();
            for ( int vx = 0; vx < val.size(); vx++ )
            {
                JsonNode fvNode = val.get( vx );
                issue.addFixVersion( fvNode.get( "name" ).asText() );
            }
        }
    }

    private void processComments( Issue issue, JsonNode val )
    {
        if ( val != null )
        {
            JsonNode commentsArray = val.get( "comments" );
            for ( int cx = 0; cx < commentsArray.size(); cx++ )
            {
                JsonNode cnode = commentsArray.get( cx );
                issue.addComment( cnode.get( "body" ).asText() );
            }
        }
    }

    private void processComponents( Issue issue, JsonNode val )
    {
        if ( val != null )
        {
            assert val.isArray();
            for ( int cx = 0; cx < val.size(); cx++ )
            {
                JsonNode cnode = val.get( cx );
                issue.addComponent( cnode.get( "name" ).asText() );
            }
        }
    }

    private void processIssueType( Issue issue, JsonNode val )
    {
        if ( val != null )
        {
            issue.setType( val.get( "name" ).asText() );
        }
    }

    private void doSessionAuth( WebClient client )
        throws IOException, MojoExecutionException, NoRest
    {
        /* if JiraUser is specified instead of WebUser, we need to make a session. */
        if ( jiraUser != null )
        {
            client.replacePath( "/rest/auth/1/session" );
            client.type( MediaType.APPLICATION_JSON_TYPE );
            StringWriter jsWriter = new StringWriter( );
            JsonGenerator gen = jsonFactory.createGenerator( jsWriter );
            gen.writeStartObject();
            gen.writeStringField( "username", jiraUser );
            gen.writeStringField( "password", jiraPassword );
            gen.writeEndObject();
            gen.close();
            Response authRes = client.post( jsWriter.toString() );
            if ( authRes.getStatus() != Response.Status.OK.getStatusCode() )
            {
                if ( authRes.getStatus() != 401 && authRes.getStatus() != 403 )
                {
                    // if not one of the documented failures, assume that there's no rest in there in the first place.
                    throw new NoRest();
                }
                throw new MojoExecutionException( String.format( "Authentication failure status %d.",
                                                                 authRes.getStatus() ) );
            }
        }
    }

    private WebClient setupWebClient( String jiraUrl )
    {
        WebClient client = WebClient.create( jiraUrl );

        ClientConfiguration clientConfiguration = WebClient.getConfig( client );
        HTTPConduit http = clientConfiguration.getHttpConduit();
        // MCHANGES-324 - Maintain the client session
        clientConfiguration.getRequestContext().put( Message.MAINTAIN_SESSION, Boolean.TRUE );

        if ( getLog().isDebugEnabled() )
        {
            clientConfiguration.getInInterceptors().add( new LoggingInInterceptor(  ) );
            clientConfiguration.getOutInterceptors().add( new LoggingOutInterceptor(  ) );
        }

        HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();

        httpClientPolicy.setConnectionTimeout( 36000 );
        httpClientPolicy.setAllowChunking( false );
        httpClientPolicy.setReceiveTimeout( 32000 );

        if ( proxyHost != null )
        {
            getLog().debug( "Using proxy: " + proxyHost + " at port " + proxyPort );
            httpClientPolicy.setProxyServer( proxyHost );
            httpClientPolicy.setProxyServerPort( proxyPort );
            httpClientPolicy.setProxyServerType( ProxyServerType.HTTP );
            if ( proxyUser != null )
            {
                ProxyAuthorizationPolicy proxyAuthorizationPolicy = new ProxyAuthorizationPolicy();
                proxyAuthorizationPolicy.setAuthorizationType( "Basic" );
                proxyAuthorizationPolicy.setUserName( proxyUser );
                proxyAuthorizationPolicy.setPassword( proxyPass );
                http.setProxyAuthorization( proxyAuthorizationPolicy );
            }
        }

        if ( webUser != null )
        {
            AuthorizationPolicy authPolicy = new AuthorizationPolicy();
            authPolicy.setAuthorizationType( "Basic" );
            authPolicy.setUserName( webUser );
            authPolicy.setPassword( webPassword );
            http.setAuthorization( authPolicy );
        }

        http.setClient( httpClientPolicy );
        return client;
    }

    public List<Issue> getIssueList() throws MojoExecutionException
    {
        return issueList;
    }
}
