package usda.weru.remoteDataAccess.csip;

import ex1.NotePrinter;
import java.beans.PropertyChangeSupport;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import org.apache.commons.io.FileUtils;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import usda.weru.remoteDataAccess.RdaBgCacheContIf;
import usda.weru.remoteDataAccess.RdaHierarchicalItem;
import usda.weru.remoteDataAccess.RdaInputController;
import usda.weru.remoteDataAccess.RdaInputControllerCachingSupport;
import usda.weru.remoteDataAccess.exceptions.BackgroundLoadException;
import usda.weru.remoteDataAccess.exceptions.BackgroundLoadException.BackgroundLoadExceptionType;
import usda.weru.remoteDataAccess.exceptions.RdaConnectException;

/**
 *
 * @author mhaas
 */
public class CsipInputControllerCachingSupport extends RdaInputControllerCachingSupport {

    Logger LOGGER = LogManager.getLogger(CsipInputControllerCachingSupport.class);

    protected SwingWorker<ArrayList<String>, Object> backgroundTask;

    public static final String PROP_CSIP_BGCATALOG_COMPLETE = "PropCsipBgCatalogComplete";
    public static final String PROP_CSIP_BGCATALOG_STARTING = "PropCsipBgCatalogStarting";
    
    public CsipInputControllerCachingSupport (RdaInputController controllerStatic) {
        super(controllerStatic);
        
        backgroundTask = null;
        initCsipCachingSupport();
    }
    
    public void initCsipCachingSupport () {
        if (rdaController != null) {
            rdaInterface = rdaController.getInterface();
        }
    }
    
    public File getFileCaching(RdaHierarchicalItem item, CsipInterface csipIf) throws RdaConnectException {
        File cachedFile = getCsipCachedFile(item);
        if (cachedFile != null) {
            System.out.println("CsipInputController: using cached file: " + cachedFile.getAbsolutePath());
            return cachedFile;
        } else {
            System.out.println("CsipInputController: no cached file.");
            return copyCsipFileToCache(csipIf.callCsipGetRecord(item.getName(), item.getParentPath()), item);
        }
    }
    
    public File getCsipCachedFile (RdaHierarchicalItem item) throws RdaConnectException {
        File f = getFileFromParsedItem(item);
        return f.exists() ? f : null;
    }

    protected File getFileFromParsedItem (RdaHierarchicalItem fileItem) {
        return getFileFromParsedItem (fileItem, baseCacheDir);
    }
    
    protected File getFileFromParsedItem (RdaHierarchicalItem fileItem, File baseCacheDir) {
        // some names have "/" in the middle of the names, NOT as a dir separator.
        // get rid of it when actually creating file names...
        String path = fileItem.getParentPath();
        path = path.replace("/", "-") + "\\";
        path = path.replace("\\", "/");
        return new File (baseCacheDir + "/" + path, fileItem.getName());
    }
    
    protected File copyCsipFileToCache (File csipFile, RdaHierarchicalItem item) throws RdaConnectException {
        try {
            FileUtils.copyFile(csipFile, getFileFromParsedItem(item));
            cacheAddToCatalog(item.getParentPath() + "\\" + item.getName());
        } catch (Exception ex) {
            throw (new RdaConnectException("Unable to copy CSIP file to cache", ex, this.interfaceName));
        }
        return csipFile;
    }

    public void doBackgroundGetCatalog (RdaHierarchicalItem inputDataTree, CsipInterface csipIf, PropertyChangeSupport changes) {
                                
        RdaBgCacheContIf controller = (rdaController instanceof RdaBgCacheContIf) ?
                                                     (RdaBgCacheContIf)rdaController : null;

        fireCatStarting(changes);
        
        if (backgroundTask != null) {
            backgroundTask.cancel(true);
        }
        backgroundTask = new SwingWorker<ArrayList<String>, Object>() {

            @Override
            public ArrayList<String> doInBackground() throws BackgroundLoadException {
                try {
                    return csipIf.callCsipCatalog();
                } catch (RdaConnectException ex) {
                    LOGGER.log(Level.INFO,
                        "cacheFiles Background catalog " + interfaceName + 
                        " failed to fetch catalog");
                    
                    if (controller != null) {
                        try {
                            LOGGER.log(Level.INFO,
                                             "reading cached catalog for " + interfaceName);
                            System.out.println("reading cached catalog for " + interfaceName);

                            return controller.cacheReadCatalog();
                        } catch (IOException ex1) {
                            LOGGER.log(Level.INFO,
                                "cacheFiles Background read cached catalog " + interfaceName + 
                                " failed to read cached catalog");
                        throw new BackgroundLoadException ("Could not connect", ex, 
                                                            "doBackgroundGetCatalog", 
                                                            BackgroundLoadExceptionType.CONNECTION);
                        }
                    }
                }
                return null;
            }

             @Override
            protected void done() {
                boolean isInCache = false;
                
                try {
                    ArrayList<String>lmodResults = get();
                    //System.out.println ("CsipInputController, done task, catalog list len = " + lmodResults.size());
                    if (lmodResults != null) {
                        if (controller != null) {
                            isInCache = controller.cacheWriteCatalog(lmodResults);
                        }
                        if (inputDataTree instanceof CsipHierarchicalItem) {
                            for (String lmodItem : lmodResults) {
                                ((CsipHierarchicalItem)inputDataTree).addPath (lmodItem);
                            }
                        }

//                        fireCatComplete (changes, isInCache);
                    }

                    //System.out.println("CsipBackground load catalog complete:"+interfaceName);
                    backgroundTask = null;

                } catch (Exception e) {
                    isInCache = false;
                    Throwable ee = e.getCause();
                    if (ee instanceof BackgroundLoadException) {
                        throw new RuntimeException ("doBackgroundGetCatalog failed, interfaceName="+interfaceName, ee);
                    }
                } finally {
                    fireCatComplete (changes, isInCache);                    
                }
            }
        };
        backgroundTask.execute();
    }
    
    protected void fireCatComplete (PropertyChangeSupport changes, boolean isInCache) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                changes.firePropertyChange(PROP_CSIP_BGCATALOG_COMPLETE, 3, isInCache);
            }
        });
    }
    
    protected void fireCatStarting (PropertyChangeSupport changes) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                changes.firePropertyChange(PROP_CSIP_BGCATALOG_STARTING, 3, false);
            }
        });
    }
}
