package org.apache.maven.surefire.junitcore.pc;

/*
 * 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.surefire.junitcore.JUnitCoreParameters;
import org.apache.maven.surefire.testset.TestSetFailedException;
import org.junit.runner.Description;

import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;

/**
 * An algorithm which configures {@link ParallelComputer} with allocated thread resources by given
 * {@link org.apache.maven.surefire.junitcore.JUnitCoreParameters}.
 * The {@code AbstractSurefireMojo} has to provide correct combinations of thread-counts and
 * configuration parameter {@code parallel}.
 *
 * @author Tibor Digana (tibor17)
 * @see org.apache.maven.surefire.junitcore.pc.ParallelComputerBuilder
 * @since 2.16
 */
final class ParallelComputerUtil
{
    private static final Collection<Description> UNUSED_DESCRIPTIONS =
            Arrays.asList( null, Description.createSuiteDescription( "null" ), Description.TEST_MECHANISM,
                    Description.EMPTY );

    private static int availableProcessors = Runtime.getRuntime().availableProcessors();

    private ParallelComputerUtil()
    {
        throw new IllegalStateException( "Suppresses calling constructor, ensuring non-instantiability." );
    }

    /*
    * For testing purposes.
    */
    static void overrideAvailableProcessors( int availableProcessors )
    {
        ParallelComputerUtil.availableProcessors = availableProcessors;
    }

    /*
    * For testing purposes.
    */
    static void setDefaultAvailableProcessors()
    {
        ParallelComputerUtil.availableProcessors = Runtime.getRuntime().availableProcessors();
    }

    static Concurrency resolveConcurrency( JUnitCoreParameters params, RunnerCounter counts )
        throws TestSetFailedException
    {
        if ( !params.isParallelismSelected() )
        {
            throw new TestSetFailedException( "Unspecified parameter '" + JUnitCoreParameters.PARALLEL_KEY + "'." );
        }

        if ( !params.isUseUnlimitedThreads() && !hasThreadCount( params ) && !hasThreadCounts( params ) )
        {
            throw new TestSetFailedException( "Unspecified thread-count(s). "
                                                  + "See the parameters "
                                                  + JUnitCoreParameters.USEUNLIMITEDTHREADS_KEY + ", "
                                                  + JUnitCoreParameters.THREADCOUNT_KEY + ", "
                                                  + JUnitCoreParameters.THREADCOUNTSUITES_KEY + ", "
                                                  + JUnitCoreParameters.THREADCOUNTCLASSES_KEY + ", "
                                                  + JUnitCoreParameters.THREADCOUNTMETHODS_KEY + "." );
        }

        if ( params.isUseUnlimitedThreads() )
        {
            return concurrencyForUnlimitedThreads( params );
        }
        else if ( hasThreadCount( params ) )
        {
            if ( hasThreadCounts( params ) )
            {
                return isLeafUnspecified( params )
                    ? concurrencyFromAllThreadCountsButUnspecifiedLeafCount( params, counts )
                    : concurrencyFromAllThreadCounts( params );
            }
            else
            {
                return estimateConcurrency( params, counts );
            }
        }
        else
        {
            return concurrencyFromThreadCounts( params );
        }
    }

    static boolean isUnusedDescription( Description examined )
    {
        if ( UNUSED_DESCRIPTIONS.contains( examined ) )
        {
            return true;
        }
        else
        {
            // UNUSED_DESCRIPTIONS ensures that "examined" cannot be null
            for ( Description unused : UNUSED_DESCRIPTIONS )
            {
                if ( unused != null && unused.getDisplayName().equals( examined.getDisplayName() ) )
                {
                    return true;
                }
            }
            return false;
        }
    }

    static void removeUnusedDescriptions( Collection<Description> examined )
    {
        for ( Iterator<Description> it = examined.iterator(); it.hasNext(); )
        {
            if ( isUnusedDescription( it.next() ) )
            {
                it.remove();
            }
        }
    }

    private static Concurrency concurrencyForUnlimitedThreads( JUnitCoreParameters params )
    {
        Concurrency concurrency = new Concurrency();
        concurrency.suites = params.isParallelSuites() ? threadCountSuites( params ) : 0;
        concurrency.classes = params.isParallelClasses() ? threadCountClasses( params ) : 0;
        concurrency.methods = params.isParallelMethods() ? threadCountMethods( params ) : 0;
        concurrency.capacity = Integer.MAX_VALUE;
        return concurrency;
    }

    private static Concurrency estimateConcurrency( JUnitCoreParameters params, RunnerCounter counts )
    {
        final Concurrency concurrency = new Concurrency();
        final int parallelEntities = countParallelEntities( params );
        concurrency.capacity = multiplyByCoreCount( params, params.getThreadCount() );
        if ( parallelEntities == 1 || counts == null || counts.classes == 0 )
        {
            // Estimate parallel thread counts.
            double ratio = 1d / parallelEntities;
            int threads = multiplyByCoreCount( params, ratio * params.getThreadCount() );
            concurrency.suites = params.isParallelSuites() ? minSuites( threads, counts ) : 0;
            concurrency.classes = params.isParallelClasses() ? minClasses( threads, counts ) : 0;
            concurrency.methods = params.isParallelMethods() ? minMethods( threads, counts ) : 0;
            if ( parallelEntities == 1 )
            {
                concurrency.capacity = 0;
            }
            else
            {
                adjustLeaf( params, concurrency );
            }
        }
        else
        {
            // Try to allocate suites+classes+methods within threadCount,
            concurrency.suites = params.isParallelSuites() ? toNonNegative( counts.suites ) : 0;
            concurrency.classes = params.isParallelClasses() ? toNonNegative( counts.classes ) : 0;
            concurrency.methods =
                params.isParallelMethods() ? toNonNegative( Math.ceil( counts.methods / (double) counts.classes ) ) : 0;
            double sum = toNonNegative( concurrency.suites + concurrency.classes + concurrency.methods );
            if ( concurrency.capacity < sum && sum != 0 )
            {
                // otherwise allocate them using the weighting factor < 1.
                double weight = concurrency.capacity / sum;
                concurrency.suites *= weight;
                concurrency.classes *= weight;
                concurrency.methods *= weight;
            }
            adjustLeaf( params, concurrency );
        }
        return concurrency;
    }

    private static Concurrency concurrencyFromAllThreadCountsButUnspecifiedLeafCount( JUnitCoreParameters params,
                                                                                      RunnerCounter counts )
    {
        Concurrency concurrency = new Concurrency();
        concurrency.suites = params.isParallelSuites() ? params.getThreadCountSuites() : 0;
        concurrency.suites = params.isParallelSuites() ? multiplyByCoreCount( params, concurrency.suites ) : 0;
        concurrency.classes = params.isParallelClasses() ? params.getThreadCountClasses() : 0;
        concurrency.classes = params.isParallelClasses() ? multiplyByCoreCount( params, concurrency.classes ) : 0;
        concurrency.methods = params.isParallelMethods() ? params.getThreadCountMethods() : 0;
        concurrency.methods = params.isParallelMethods() ? multiplyByCoreCount( params, concurrency.methods ) : 0;
        concurrency.capacity = multiplyByCoreCount( params, params.getThreadCount() );

        if ( counts != null )
        {
            concurrency.suites = toNonNegative( Math.min( concurrency.suites, counts.suites ) );
            concurrency.classes = toNonNegative( Math.min( concurrency.classes, counts.classes ) );
        }

        setLeafInfinite( params, concurrency );

        return concurrency;
    }

    private static Concurrency concurrencyFromAllThreadCounts( JUnitCoreParameters params )
    {
        Concurrency concurrency = new Concurrency();
        concurrency.suites = params.isParallelSuites() ? params.getThreadCountSuites() : 0;
        concurrency.classes = params.isParallelClasses() ? params.getThreadCountClasses() : 0;
        concurrency.methods = params.isParallelMethods() ? params.getThreadCountMethods() : 0;
        concurrency.capacity = params.getThreadCount();
        double all = sumThreadCounts( concurrency );

        concurrency.suites = params.isParallelSuites() ? multiplyByCoreCount( params, concurrency.capacity * (
            concurrency.suites / all ) ) : 0;

        concurrency.classes = params.isParallelClasses() ? multiplyByCoreCount( params, concurrency.capacity * (
            concurrency.classes / all ) ) : 0;

        concurrency.methods = params.isParallelMethods() ? multiplyByCoreCount( params, concurrency.capacity * (
            concurrency.methods / all ) ) : 0;

        concurrency.capacity = multiplyByCoreCount( params, concurrency.capacity );
        adjustPrecisionInLeaf( params, concurrency );
        return concurrency;
    }

    private static Concurrency concurrencyFromThreadCounts( JUnitCoreParameters params )
    {
        Concurrency concurrency = new Concurrency();
        concurrency.suites = params.isParallelSuites() ? threadCountSuites( params ) : 0;
        concurrency.classes = params.isParallelClasses() ? threadCountClasses( params ) : 0;
        concurrency.methods = params.isParallelMethods() ? threadCountMethods( params ) : 0;
        concurrency.capacity = toNonNegative( sumThreadCounts( concurrency ) );
        return concurrency;
    }

    private static int countParallelEntities( JUnitCoreParameters params )
    {
        int count = 0;
        if ( params.isParallelSuites() )
        {
            count++;
        }

        if ( params.isParallelClasses() )
        {
            count++;
        }

        if ( params.isParallelMethods() )
        {
            count++;
        }
        return count;
    }

    private static void adjustPrecisionInLeaf( JUnitCoreParameters params, Concurrency concurrency )
    {
        if ( params.isParallelMethods() )
        {
            concurrency.methods = concurrency.capacity - concurrency.suites - concurrency.classes;
        }
        else if ( params.isParallelClasses() )
        {
            concurrency.classes = concurrency.capacity - concurrency.suites;
        }
    }

    private static void adjustLeaf( JUnitCoreParameters params, Concurrency concurrency )
    {
        if ( params.isParallelMethods() )
        {
            concurrency.methods = Integer.MAX_VALUE;
        }
        else if ( params.isParallelClasses() )
        {
            concurrency.classes = Integer.MAX_VALUE;
        }
    }

    private static void setLeafInfinite( JUnitCoreParameters params, Concurrency concurrency )
    {
        if ( params.isParallelMethods() )
        {
            concurrency.methods = Integer.MAX_VALUE;
        }
        else if ( params.isParallelClasses() )
        {
            concurrency.classes = Integer.MAX_VALUE;
        }
        else if ( params.isParallelSuites() )
        {
            concurrency.suites = Integer.MAX_VALUE;
        }
    }

    private static boolean isLeafUnspecified( JUnitCoreParameters params )
    {
        int maskOfParallel = params.isParallelSuites() ? 4 : 0;
        maskOfParallel |= params.isParallelClasses() ? 2 : 0;
        maskOfParallel |= params.isParallelMethods() ? 1 : 0;

        int maskOfConcurrency = params.getThreadCountSuites() > 0 ? 4 : 0;
        maskOfConcurrency |= params.getThreadCountClasses() > 0 ? 2 : 0;
        maskOfConcurrency |= params.getThreadCountMethods() > 0 ? 1 : 0;

        maskOfConcurrency &= maskOfParallel;

        int leaf = Integer.lowestOneBit( maskOfParallel );
        return maskOfConcurrency == maskOfParallel - leaf;
    }

    private static double sumThreadCounts( Concurrency concurrency )
    {
        double sum = concurrency.suites;
        sum += concurrency.classes;
        sum += concurrency.methods;
        return sum;
    }

    private static boolean hasThreadCounts( JUnitCoreParameters jUnitCoreParameters )
    {
        return ( jUnitCoreParameters.isParallelSuites() && jUnitCoreParameters.getThreadCountSuites() > 0 )
            || ( jUnitCoreParameters.isParallelClasses() && jUnitCoreParameters.getThreadCountClasses() > 0 )
            || ( jUnitCoreParameters.isParallelMethods() && jUnitCoreParameters.getThreadCountMethods() > 0 );
    }

    private static boolean hasThreadCount( JUnitCoreParameters jUnitCoreParameters )
    {
        return jUnitCoreParameters.getThreadCount() > 0;
    }

    private static int threadCountMethods( JUnitCoreParameters jUnitCoreParameters )
    {
        return multiplyByCoreCount( jUnitCoreParameters, jUnitCoreParameters.getThreadCountMethods() );
    }

    private static int threadCountClasses( JUnitCoreParameters jUnitCoreParameters )
    {
        return multiplyByCoreCount( jUnitCoreParameters, jUnitCoreParameters.getThreadCountClasses() );
    }

    private static int threadCountSuites( JUnitCoreParameters jUnitCoreParameters )
    {
        return multiplyByCoreCount( jUnitCoreParameters, jUnitCoreParameters.getThreadCountSuites() );
    }

    private static int multiplyByCoreCount( JUnitCoreParameters jUnitCoreParameters, double threadsPerCore )
    {
        double numberOfThreads =
            jUnitCoreParameters.isPerCoreThreadCount() ? threadsPerCore * (double) availableProcessors : threadsPerCore;

        return numberOfThreads > 0 ? toNonNegative( numberOfThreads ) : Integer.MAX_VALUE;
    }

    private static int minSuites( int threads, RunnerCounter counts )
    {
        long count = counts == null ? Integer.MAX_VALUE : counts.suites;
        return Math.min( threads, toNonNegative( count ) );
    }

    private static int minClasses( int threads, RunnerCounter counts )
    {
        long count = counts == null ? Integer.MAX_VALUE : counts.classes;
        return Math.min( threads, toNonNegative( count ) );
    }

    private static int minMethods( int threads, RunnerCounter counts )
    {
        long count = counts == null ? Integer.MAX_VALUE : counts.methods;
        return Math.min( threads, toNonNegative( count ) );
    }

    private static int toNonNegative( long num )
    {
        return (int) Math.min( num > 0 ? num : 0, Integer.MAX_VALUE );
    }

    private static int toNonNegative( double num )
    {
        return (int) Math.min( num > 0 ? num : 0, Integer.MAX_VALUE );
    }
}