package ai.subut.kurjun.repo.cache;


import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import ai.subut.kurjun.metadata.common.utils.MetadataUtils;
import ai.subut.kurjun.model.metadata.Metadata;
import ai.subut.kurjun.model.metadata.MetadataCache;
import ai.subut.kurjun.model.metadata.SerializableMetadata;
import ai.subut.kurjun.model.repository.Repository;


public class MetadataCacheImpl implements MetadataCache
{

    private final Repository repository;

    private volatile boolean inited;
    private final List<SerializableMetadata> metadata = new ArrayList<>();

    private final ExecutorService executor = Executors.newSingleThreadExecutor();
    private final Lock lock = new ReentrantLock();


    /**
     * Constructs meta data cache for the supplied repository.
     *
     * @param repository repository whose packages metadata will be cached
     */
    MetadataCacheImpl( Repository repository )
    {
        this.repository = repository;
    }


    @Override
    public List<SerializableMetadata> getMetadataList()
    {
        if ( !inited )
        {
            refresh();
        }
        return Collections.unmodifiableList( metadata );
    }


    @Override
    public SerializableMetadata get( byte[] md5 )
    {
        Objects.requireNonNull( md5, "MD5 checksum" );

        if ( !inited )
        {
            refresh();
        }
        for ( SerializableMetadata m : metadata )
        {
            if ( Arrays.equals( m.getMd5Sum(), md5 ) )
            {
                return m;
            }
        }
        return null;
    }


    @Override
    public SerializableMetadata get( String name, String version )
    {
        Objects.requireNonNull( name, "Name in meta data" );

        if ( !inited )
        {
            refresh();
        }
        if ( version != null )
        {
            for ( SerializableMetadata m : metadata )
            {
                if ( name.equals( m.getName() ) && version.equals( m.getVersion() ) )
                {
                    return m;
                }
            }
        }
        else
        {
            Comparator<Metadata> cmp = Collections.reverseOrder( MetadataUtils.makeVersionComparator() );
            Object[] arr = metadata.stream().filter( m -> m.getName().equals( name ) ).sorted( cmp ).toArray();
            if ( arr.length > 0 )
            {
                return ( SerializableMetadata ) arr[0];
            }
        }
        return null;
    }


    @Override
    public void refresh()
    {
        List<SerializableMetadata> items = repository.listPackages();

        lock.lock();
        try
        {
            metadata.clear();
            metadata.addAll( items );
            inited = true;
        }
        finally
        {
            lock.unlock();
        }
    }


    public void refreshTrigger()
    {
        executor.submit( new Runnable()
        {
            @Override
            public void run()
            {
                refresh();
            }
        } );
    }
}


@@ -196,92 +196,8 @@
 ts;%0A
-import java.util.concurrent.ExecutorService;%0Aimport java.util.concurrent.Executors;%0A
 impo
@@ -775,90 +775,8 @@
 );%0A%0A
-    private final ExecutorService executor = Executors.newSingleThreadExecutor();%0A
     
@@ -2929,222 +2929,7 @@
 %7D%0A%0A%0A
-    public void refreshTrigger()%0A    %7B%0A        executor.submit( new Runnable()%0A        %7B%0A            @Override%0A            public void run()%0A            %7B%0A                refresh();%0A            %7D%0A        %7D );%0A    %7D%0A
 %7D%0A%0A

remove unused refresh trigger