package org.commonjava.indy.content.index.warmer;

import org.commonjava.cdi.util.weft.ExecutorConfig;
import org.commonjava.cdi.util.weft.WeftManaged;
import org.commonjava.indy.IndyWorkflowException;
import org.commonjava.indy.content.DownloadManager;
import org.commonjava.indy.content.index.ContentIndexManager;
import org.commonjava.indy.data.IndyDataException;
import org.commonjava.indy.data.StoreDataManager;
import org.commonjava.indy.model.core.ArtifactStore;
import org.commonjava.indy.model.core.Group;
import org.commonjava.indy.model.core.StoreKey;
import org.commonjava.indy.model.core.StoreType;
import org.commonjava.maven.galley.model.Transfer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;

@ApplicationScoped
public class ContentIndexWarmer
{
    @Inject
    private ContentIndexManager indexManager;

    @Inject
    private StoreDataManager storeDataManager;

    @Inject
    private DownloadManager downloadManager;

    @WeftManaged
    @ExecutorConfig( named = "content-index-warmer", priority = 6, threads = 12 )
    @Inject
    private ExecutorService executor;

    private final Logger logger = LoggerFactory.getLogger( getClass() );

    public void warmCaches()
    {
        executor.submit( ()->{
            Map<StoreKey, List<Transfer>> transferMap = new ConcurrentHashMap<>();

            try
            {
                List<ArtifactStore> concreteStores = storeDataManager.query().storeTypes( StoreType.hosted, StoreType.remote ).getAll();

                CountDownLatch latch = new CountDownLatch( concreteStores.size() );

                concreteStores.forEach( store -> executor.submit( () -> {
                    try
                    {
                        List<Transfer> transfers = downloadManager.listRecursively( store.getKey(), DownloadManager.ROOT_PATH );
                        transferMap.put( store.getKey(), transfers );
                        transfers.forEach( t->indexManager.indexTransferIn( t, store.getKey() ) );
                    }
                    catch ( IndyWorkflowException e )
                    {
                        logger.warn( "Failed to retrieve root directory of storage for: " + store.getKey(),
                                     e );
                    }
                    finally
                    {
                        latch.countDown();
                    }
                } ) );

                try
                {
                    latch.await();
                }
                catch ( InterruptedException e )
                {
                    logger.info("Manager thread interrupted while waiting for concrete store indexing to complete.");
                    return;
                }

                storeDataManager.query().storeType( Group.class ).stream().forEach( g-> executor.submit(() -> {
                    StoreKey gkey = g.getKey();

                    g.getConstituents()
                     .stream()
                     .filter( m -> m.getType() != StoreType.group && transferMap.containsKey( m ) )
                     .forEach( m -> {
                         List<Transfer> txfrs = transferMap.get( m );
                         txfrs.forEach( t -> {
                             if ( indexManager.getIndexedStorePath( gkey, t.getPath() ) == null )
                             {
                                 indexManager.indexTransferIn( t, gkey );
                             }
                         } );
                     } );
                } ) );
            }
            catch ( IndyDataException e )
            {
                logger.warn( "Content index warm-up failed: %s", e, e.getMessage() );
            }

            logger.info( "Content index cache has been re-established." );

        } );
    }
}

@@ -3195,27 +3195,11 @@
     
-g.getConstituents()
+try
 %0A   
@@ -3219,118 +3219,168 @@
     
- .stream()%0A                     .filter( m -%3E m.getType() != StoreType.group && transferMap.containsKey( m 
+%7B%0A                        List%3CArtifactStore%3E stores =%0A                                storeDataManager.query().getOrderedConcreteStoresInGroup( g.getName(
 ) )
+;%0A
 %0A   
@@ -3397,16 +3397,25 @@
         
+   stores
 .forEach
@@ -3420,15 +3420,19 @@
 ch( 
-m
+s
  -%3E %7B%0A
+    
     
@@ -3496,13 +3496,26 @@
 et( 
-m );%0A
+s.getKey() );%0A    
     
@@ -3553,24 +3553,28 @@
 ach( t -%3E %7B%0A
+    
             
@@ -3680,34 +3680,42 @@
                 
+ 
-%7B%0A
+   %7B%0A    
                 
@@ -3793,34 +3793,41 @@
                 
-%7D%0A
+    %7D%0A   
                 
@@ -3827,32 +3827,33 @@
                 
+ 
 %7D );%0A           
@@ -3854,36 +3854,265 @@
                 
-%7D );
+    %7D );%0A                    %7D%0A                    catch ( IndyDataException e )%0A                    %7B%0A                        logger.warn( %22Failed to get ordered concrete stores for group: %22 + g.getName(), e );%0A                    %7D
 %0A               

fix content index warm-up for group index entries