package org.commonjava.indy.repo.proxy.content;

import org.commonjava.indy.IndyWorkflowException;
import org.commonjava.indy.content.ContentManager;
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.StoreKey;
import org.commonjava.indy.model.galley.KeyedLocation;
import org.commonjava.indy.repo.proxy.conf.RepoProxyConfig;
import org.commonjava.indy.subsys.infinispan.CacheHandle;
import org.commonjava.indy.util.LocationUtils;
import org.commonjava.maven.galley.event.FileStorageEvent;
import org.infinispan.notifications.Listener;
import org.infinispan.notifications.cachelistener.annotation.CacheEntriesEvicted;
import org.infinispan.notifications.cachelistener.annotation.CacheEntryExpired;
import org.infinispan.notifications.cachelistener.event.CacheEntriesEvictedEvent;
import org.infinispan.notifications.cachelistener.event.CacheEntryExpiredEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.event.Observes;
import javax.inject.Inject;
import java.util.Map;

@ApplicationScoped
@Listener
public class RepoProxyContentLimiter
{

    private CacheHandle<String, String> storedPaths;

    private RepoProxyConfig config;

    private StoreDataManager storeDataManager;

    private ContentManager contentManager;

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

    @Inject
    public RepoProxyContentLimiter( @RepoProxyContentCache CacheHandle<String, String> storedPaths,
                                    StoreDataManager storeDataManager, ContentManager contentManager,
                                    RepoProxyConfig config )
    {
        this.storedPaths = storedPaths;
        this.storeDataManager = storeDataManager;
        this.contentManager = contentManager;
        this.config = config;
    }

    public void onContentStorage( @Observes FileStorageEvent storageEvent )
    {
        if ( !isEnabled() )
        {
            return;
        }

        StoreKey storeKey = LocationUtils.getKey( storageEvent );
        String path = storageEvent.getTransfer().getPath();
        String skp = storeKey.toString() + "#" + path;

        storedPaths.put( skp, skp );
    }

    private boolean isEnabled()
    {
        return config.isEnabled() && config.isContentLimiterEnabled();
    }

    @CacheEntryExpired
    public void onContentExpiration( CacheEntryExpiredEvent<String, String> event )
    {
        if ( !isEnabled() )
        {
            return;
        }

        clearContent( event.getKey() );
    }

    @CacheEntriesEvicted
    public void onContentEviction( CacheEntriesEvictedEvent<String, String> event )
    {
        if ( !isEnabled() )
        {
            return;
        }

        Map<String, String> entries = event.getEntries();
        for ( String skp : entries.keySet() )
        {
            clearContent( skp );
        }
    }

    private void clearContent( String skp )
    {
        String[] parts = skp.split( "#" );
        StoreKey storeKey = StoreKey.fromString( parts[0] );
        ArtifactStore store = null;
        try
        {
            store = storeDataManager.getArtifactStore( storeKey );
            contentManager.delete( store, parts[1] );
        }
        catch ( IndyDataException e )
        {
            logger.warn( "Failed to lookup store: {} from event: {}", storeKey, skp );
        }
        catch ( IndyWorkflowException e )
        {
            logger.warn( "Failed to delete: {} from: {}, from event: {}", parts[1], storeKey, skp );
        }
    }

}

@@ -349,63 +349,8 @@
 ey;%0A
-import org.commonjava.indy.model.galley.KeyedLocation;%0A
 impo
@@ -1139,16 +1139,80 @@
 l.Map;%0A%0A
+import static org.commonjava.indy.model.core.StoreType.remote;%0A%0A
 @Applica
@@ -1284,16 +1284,22 @@
 private 
+final 
 CacheHan
@@ -1344,16 +1344,22 @@
 private 
+final 
 RepoProx
@@ -1387,16 +1387,22 @@
 private 
+final 
 StoreDat
@@ -1441,16 +1441,22 @@
 private 
+final 
 ContentM
@@ -2220,24 +2220,82 @@
 ageEvent );%0A
+        if ( remote == storeKey.getType() )%0A        %7B%0A    
         Stri
@@ -2338,24 +2338,28 @@
 .getPath();%0A
+    
         Stri
@@ -2406,24 +2406,28 @@
 h;%0A%0A        
+    
 storedPaths.
@@ -2439,24 +2439,34 @@
 skp, skp );%0A
+        %7D%0A
     %7D%0A%0A    p
@@ -3303,24 +3303,83 @@
 parts%5B0%5D );%0A
+%0A        if ( remote == storeKey.getType() )%0A        %7B%0A    
         Arti
@@ -3397,17 +3397,14 @@
 tore
- = null;%0A
+;%0A    
     
@@ -3411,34 +3411,42 @@
     try%0A        
-%7B%0A
+    %7B%0A    
             stor
@@ -3508,16 +3508,20 @@
         
+  
+  
 contentM
@@ -3558,34 +3558,40 @@
  );%0A        
-%7D%0A
+    %7D%0A  
         
 catch ( Indy
@@ -3570,32 +3570,34 @@
     %7D%0A          
+  
 catch ( IndyData
@@ -3610,34 +3610,40 @@
 ion e )%0A        
-%7B%0A
+    %7B%0A  
             logg
@@ -3630,32 +3630,34 @@
 %7B%0A              
+  
 logger.warn( %22Fa
@@ -3715,34 +3715,42 @@
  skp );%0A        
-%7D%0A
+    %7D%0A    
         catch ( 
@@ -3775,34 +3775,40 @@
 ion e )%0A        
-%7B%0A
+    %7B%0A  
             logg
@@ -3795,32 +3795,34 @@
 %7B%0A              
+  
 logger.warn( %22Fa
@@ -3886,32 +3886,46 @@
 toreKey, skp );%0A
+            %7D%0A
         %7D%0A    %7D%0A

Add remote filter for RepoProxyContentLimiter