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 org.apache.maven.plugin.logging.Log;

import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

/**
 * JIRA 3.x way of constructing a search query based on URL parameters.
 * 
 * @author ton.swieb@finalist.com
 * @version $Id$
 * @since 2.8
 */
public class ParameterQueryBuilder
    implements JiraQueryBuilder
{
    private String filter = "";
    /** Log for debug output. */
    private Log log;
    private StringBuilder query = new StringBuilder();

    /** Mapping containing all allowed JIRA priority values. */
    private final Map<String,String> priorityMap = new HashMap<String,String>( 8 );
    /** Mapping containing all allowed JIRA resolution values. */
    private final Map<String,String> resolutionMap = new HashMap<String,String>( 8 );
    /** Mapping containing all allowed JIRA status values. */
    private final Map<String,String> statusMap = new HashMap<String,String>( 8 );
    /** Mapping containing all allowed JIRA type values. */
    private final Map<String,String> typeMap = new HashMap<String,String>( 8 );

    public ParameterQueryBuilder( Log log )
    {
        this.log = log;

        priorityMap.put( "Blocker", "1" );
        priorityMap.put( "Critical", "2" );
        priorityMap.put( "Major", "3" );
        priorityMap.put( "Minor", "4" );
        priorityMap.put( "Trivial", "5" );

        resolutionMap.put( "Unresolved", "-1" );
        resolutionMap.put( "Fixed", "1" );
        resolutionMap.put( "Won't Fix", "2" );
        resolutionMap.put( "Duplicate", "3" );
        resolutionMap.put( "Incomplete", "4" );
        resolutionMap.put( "Cannot Reproduce", "5" );

        statusMap.put( "Open", "1" );
        statusMap.put( "In Progress", "3" );
        statusMap.put( "Reopened", "4" );
        statusMap.put( "Resolved", "5" );
        statusMap.put( "Closed", "6" );

        typeMap.put( "Bug", "1" );
        typeMap.put( "New Feature", "2" );
        typeMap.put( "Task", "3" );
        typeMap.put( "Improvement", "4" );
        typeMap.put( "Wish", "5" );
        typeMap.put( "Test", "6" );
        typeMap.put( "Sub-task", "7" );
    }

    public String build()
    {
        // If the user has defined a filter - use that
        if ( ( this.filter != null ) && ( this.filter.length() > 0 ) )
        {
            return this.filter;
        }
        else
        {
            return query.toString();
        }
    }

    public JiraQueryBuilder components( String components )
    {
        // add components
        if ( components != null )
        {
            String[] componentsArr = components.split( "," );

            for ( String component : componentsArr )
            {
                component = component.trim();
                if ( component.length() > 0 )
                {
                    query.append( "&component=" ).append( component );
                }
            }
        }
        return this;
    }

    public JiraQueryBuilder components( List<String> components )
    {
        // add components
        if ( components != null )
        {
            for ( String component : components )
            {
                component = component.trim();
                if ( component.length() > 0 )
                {
                    query.append( "&component=" ).append( component );
                }
            }
        }
        return this;
    }

    public JiraQueryBuilder filter( String filter )
    {
        this.filter = filter;
        return this;
    }

    /**
     * This method has no effect in this implementation.
     */
    public JiraQueryBuilder fixVersion( String fixVersion )
    {
        return this;
    }

    public JiraQueryBuilder fixVersionIds( String fixVersionIds )
    {
        // add fix versions
        if ( fixVersionIds != null )
        {
            String[] fixVersions = fixVersionIds.split( "," );

            for ( int i = 0; i < fixVersions.length; i++ )
            {
                if ( fixVersions[i].length() > 0 )
                {
                    query.append( "&fixfor=" ).append( fixVersions[i].trim() );
                }
            }
        }
        return this;
    }

    public JiraQueryBuilder fixVersionIds( List<String> fixVersionIds )
    {
        throw new RuntimeException( "fixVersionIds(List) not supported for very old parameter queries." );
    }

    public Log getLog()
    {
        return log;
    }

    public JiraQueryBuilder priorityIds( String priorityIds )
    {
        // get the Priority Ids
        if ( priorityIds != null )
        {
            String[] prios = priorityIds.split( "," );

            for ( String prio : prios )
            {
                prio = prio.trim();
                String priorityParam = priorityMap.get( prio );

                if ( priorityParam != null )
                {
                    query.append( "&priorityIds=" ).append( priorityParam );
                }
            }
        }
        return this;
    }

    public JiraQueryBuilder priorityIds( List<String> priorityIds )
    {
        throw new RuntimeException( "priorityIds(List) not supported for old parameter queries." );
    }

    /**
     * This method has no effect in this implementation.
     */
    public JiraQueryBuilder project( String project )
    {
        return this;
    }

    public JiraQueryBuilder resolutionIds( String resolutionIds )
    {
        // get the Resolution Ids
        if ( resolutionIds != null )
        {
            String[] resos = resolutionIds.split( "," );

            for ( String reso : resos )
            {
                reso = reso.trim();
                String resoParam = resolutionMap.get( reso );

                if ( resoParam != null )
                {
                    query.append( "&resolutionIds=" ).append( resoParam );
                }
            }
        }
        return this;
    }

    public JiraQueryBuilder resolutionIds( List<String> resolutionIds )
    {
        throw new RuntimeException( "resolutionIds(List) not supported for old ParameterQueryBuilder" );
    }

    public JiraQueryBuilder sortColumnNames( String sortColumnNames )
    {
        // get the Sort order
        int validSortColumnNames = 0;
        if ( sortColumnNames != null )
        {
            String[] sortColumnNamesArray = sortColumnNames.split( "," );
            // N.B. Add in reverse order (it's the way JIRA 3 likes it!!)
            for ( int i = sortColumnNamesArray.length - 1; i >= 0; i-- )
            {
                String lowerColumnName = sortColumnNamesArray[i].trim().toLowerCase( Locale.ENGLISH );
                boolean descending = false;
                String fieldName = null;
                if ( lowerColumnName.endsWith( "desc" ) )
                {
                    descending = true;
                    lowerColumnName = lowerColumnName.substring( 0, lowerColumnName.length() - 4 ).trim();
                }
                else if ( lowerColumnName.endsWith( "asc" ) )
                {
                    descending = false;
                    lowerColumnName = lowerColumnName.substring( 0, lowerColumnName.length() - 3 ).trim();
                }

                if ( "key".equals( lowerColumnName ) )
                {
                    fieldName = "issuekey";
                }
                else if ( "summary".equals( lowerColumnName ) )
                {
                    fieldName = lowerColumnName;
                }
                else if ( "status".equals( lowerColumnName ) )
                {
                    fieldName = lowerColumnName;
                }
                else if ( "resolution".equals( lowerColumnName ) )
                {
                    fieldName = lowerColumnName;
                }
                else if ( "assignee".equals( lowerColumnName ) )
                {
                    fieldName = lowerColumnName;
                }
                else if ( "reporter".equals( lowerColumnName ) )
                {
                    fieldName = lowerColumnName;
                }
                else if ( "type".equals( lowerColumnName ) )
                {
                    fieldName = "issuetype";
                }
                else if ( "priority".equals( lowerColumnName ) )
                {
                    fieldName = lowerColumnName;
                }
                else if ( "version".equals( lowerColumnName ) )
                {
                    fieldName = "versions";
                }
                else if ( "fix version".equals( lowerColumnName ) )
                {
                    fieldName = "fixVersions";
                }
                else if ( "component".equals( lowerColumnName ) )
                {
                    fieldName = "components";
                }
                else if ( "created".equals( lowerColumnName ) )
                {
                    fieldName = lowerColumnName;
                }
                else if ( "updated".equals( lowerColumnName ) )
                {
                    fieldName = lowerColumnName;
                }
                if ( fieldName != null )
                {
                    query.append( "&sorter/field=" );
                    query.append( fieldName );
                    query.append( "&sorter/order=" );
                    query.append( descending ? "DESC" : "ASC" );
                    validSortColumnNames++;
                }
                else
                {
                    // Error in the configuration
                    getLog().error(
                        "maven-changes-plugin: The configured value '" + lowerColumnName
                            + "' for sortColumnNames is not correct." );
                }
            }
            if ( validSortColumnNames == 0 )
            {
                // Error in the configuration
                getLog().error(
                    "maven-changes-plugin: None of the configured sortColumnNames '" + sortColumnNames + "' are correct." );
            }
        }
        return this;
    }

    public JiraQueryBuilder statusIds( String statusIds )
    {
        // get the Status Ids
        if ( statusIds != null )
        {
            String[] stats = statusIds.split( "," );
            for ( String stat : stats )
            {
                stat = stat.trim();
                String statusParam = statusMap.get( stat );

                if ( statusParam != null )
                {
                    query.append( "&statusIds=" ).append( statusParam );
                }
                else
                {
                    // if it's numeric we can handle it too.
                    try
                    {
                        Integer.parseInt( stat );
                        query.append( "&statusIds=" ).append( stat );
                    }
                    catch ( NumberFormatException nfe )
                    {
                        getLog().error( "maven-changes-plugin: invalid statusId " + stat );
                    }
                }
            }
        }
        return this;
    }

    public JiraQueryBuilder statusIds( List<String> statusIds )
    {
        throw new RuntimeException( "statusIds(List) not supported for old parameter queries." );
    }

    public JiraQueryBuilder typeIds( String typeIds )
    {
        // get the Type Ids
        if ( typeIds != null )
        {
            String[] types = typeIds.split( "," );

            for ( String type : types )
            {
                String typeParam = typeMap.get( type.trim() );

                if ( typeParam != null )
                {
                    query.append( "&type=" ).append( typeParam );
                }
            }
        }
        return this;
    }

    public JiraQueryBuilder typeIds( List<String> typeIds )
    {
        throw new RuntimeException( "typeIds(List) not supported for old ParameterQueryBuilder" );
    }
}
