package usda.weru.remoteDataAccess.csip.polygon;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import javax.swing.SwingUtilities;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import usda.weru.gis.latlong.LatLong;
import usda.weru.gis.GISUtil;
import usda.weru.remoteDataAccess.RdaBgCacheContIf;
import usda.weru.remoteDataAccess.RdaHierarchicalItem;
import usda.weru.remoteDataAccess.csip.CsipHierarchicalItem;
import usda.weru.remoteDataAccess.csip.CsipInputControllerBgCacheIf;
import usda.weru.remoteDataAccess.csip.CsipInputControllerCacheLoader;
import static usda.weru.remoteDataAccess.csip.CsipInputControllerCachingSupport.PROP_CSIP_BGCATALOG_COMPLETE;
import usda.weru.remoteDataAccess.exceptions.RdaConnectException;
import usda.weru.weps.RunFileBean;
import usda.weru.weps.RunFileData;
import usda.weru.weps.Weps;
import static usda.weru.remoteDataAccess.RdaInputControllerCacheLoader.PROP_CSIP_BGFILLCACHE_COMPLETE_INTERNAL;
import static usda.weru.remoteDataAccess.csip.crlmod.CsipInputContCrLmodBgCache.PROP_CSIP_BGFILLCACHE_COMPLETE_EXTERNAL;

/**
 *
 * @author mhaas
 */
public abstract class CsipInputContPolygonBgCache extends CsipInputContPolygon 
                                      implements RdaBgCacheContIf, CsipInputControllerBgCacheIf, PropertyChangeListener  {
    
    Logger LOGGER = LogManager.getLogger(CsipInputContPolygonBgCache.class);

    protected CsipInputContPolygonCachingSupport cachesupport;
    protected CsipInputControllerCacheLoader cacheloader;
    
    public CsipInputContPolygonBgCache () {
        this (false);
    }
    
    public CsipInputContPolygonBgCache (boolean fromSubClass) {
        super(fromSubClass);
        
        cachesupport = null;
        cacheloader = null;
    }
    
    abstract protected CsipInputContPolygonBgCache getNewCsipInputContPolygonBgCache();
    
    public CsipInputContPolygonCachingSupport getCachingSupport() {
        return cachesupport;
    }
    
    @Override
    public void setInterfaceName (String interfaceName) {
        super.setInterfaceName(interfaceName);
        cachesupport.setCacheSupportInterfaceName(interfaceName);
        cacheloader.setInterfaceName();
    }
    
    @Override
    public File getFile(RdaHierarchicalItem item) throws RdaConnectException {
        return cachesupport.getFileCaching(item, csipIf);
    }
    
    @Override
    public boolean cacheWriteCatalog (ArrayList<String> catalog) throws IOException {
        serviceResults = catalog;
        return cachesupport.cacheWriteCatalog(catalog, true);
    }
    
    @Override
    public ArrayList<String> cacheReadCatalog () throws IOException {
        return cachesupport.cacheReadCatalog();
    }
    
    @Override
    public void clearCacheDir () {
        cachesupport.clearBaseCacheDir();
    }
    
    @Override
    public void doBackgroundGetCatalog () {
        if (polygon != null) {
            downloading = true;
            filesChanged = true;
            if (inputDataTree == null) {
                RdaHierarchicalItem item = new CsipHierarchicalItem(interfaceName, this);
                inputDataTree = item;
            }
            cachesupport.doBackgroundGetCatalog(inputDataTree, csipIf, changes);
        }
    }
    
    @Override
    public void resetBackgroundTask() {
//        backgroundTask = null;
    }

    @Override
    public void propertyChange(PropertyChangeEvent evt) {
        if (evt.getPropertyName().contentEquals(PROP_CSIP_BGCATALOG_COMPLETE)) {
            downloading = false;
            boolean inCache = (evt.getNewValue() instanceof Boolean) ? ((Boolean)evt.getNewValue()) : false;
            if (!inCache) {
                if (!doCatalogOnly) {
                    doFillCache ();
                }
            } else {
                System.out.println("Background cache files previously loaded: " + interfaceName);
                LOGGER.log(Level.INFO, 
                    "Background cache files previously loaded: " + interfaceName);
            }
        } else if (evt.getPropertyName().contentEquals(PROP_CSIP_BGFILLCACHE_COMPLETE_INTERNAL)) {
            // MEH location
            // for soils
            // Need to update serviceResults var
            // it still has val from original csip catalog call
            int i = 1;
//            changes.firePropertyChange(PROP_CSIP_BGFILLCACHE_COMPLETE_EXTERNAL, false, this);
            fireLater (PROP_CSIP_BGFILLCACHE_COMPLETE_EXTERNAL);
        } else if (evt.getPropertyName().contentEquals(RunFileBean.PROP_LATLONG)) {
           int i = 1;
        } else if (evt.getPropertyName().contentEquals(RunFileData.StrLatLong) ||
                   evt.getPropertyName().contentEquals(polygonPropName)) {
            if (evt.getNewValue() != null) {
                String s = Weps.getInstance().getRunFileData().getData(RunFileData.StrLatLong);
                if (s != null ) {
                    LatLong newLatLong = GISUtil.parse(Weps.getInstance().getRunFileData().getData(RunFileData.StrLatLong));
                    if (newLatLong != null) {
                        if (polygonCenter == null || (polygonCenter != null && !polygonCenter.equals(newLatLong))) {
                            setPolygon(newLatLong);
                            if (!this.cacheFilesValid()) {
                                resetCatalog();
                                doBackgroundGetCatalog();
                            }
                        }
                    }
                }
            }
        }
}
    
    // only call this one
    @Override
    public void doFillCache () {
        // need a new independent controller object:
        //   1. it uses different destination, which is part of the controller's data
        //      This object's dest is not the same as the cacheing dir.
        //   2. avoid threading conflicts when using the CsipInterface's CSIP client object.
        //
        if (doCacheBackgroundLoad) {
            // other controllers do this once
            // For Soil, it updates and accumulates data every time latlon changes.
            // do this at most once
            //doCacheBackgroundLoad = false;
            CsipInputContPolygonBgCache tempController = getNewCsipInputContPolygonBgCache();
            tempController.setPolygon(polygonCenter);
            // init tempController with existing catalog info,, to avoid 2nd catalog call.
            // catalog very slow for soils.
            tempController.serviceResults = this.serviceResults;
            ((CsipInterfacePolygon)tempController.csipIf).setReturnTree(((CsipInterfacePolygon)csipIf).getReturnTree());
            try {
                tempController.init(inputDataTree);
            } catch (RdaConnectException ex) {
            }
            
            tempController.setInterfaceName(interfaceName);
            tempController.getChangeObj().addPropertyChangeListener(PROP_CSIP_BGFILLCACHE_COMPLETE_INTERNAL,this);
            tempController.doFillCacheInternal();
        }
    }
    
    // this one only for use from above
    @Override
    public void doFillCacheInternal() {
        cacheloader.cacheFilesInBackground(inputDataTree);
    }

    @Override
    public boolean checkBackgroundGetCatalog() {
        return downloading;
    }

    @Override
    public boolean checkNewFiles() {
        return filesChanged;
    }

    @Override
    public void clearNewFiles() {
        filesChanged = false;
    }

    @Override
    public void resetCatalog() {
        resetBackgroundTask();
        inputDataTree = null;
    }
    
    @Override
    public void addPropertyChangeListener(String propertyName, PropertyChangeListener l) {
        changes.addPropertyChangeListener(propertyName, l);
    }
    
    @Override
    public void removePropertyChangeListener(String propertyName, PropertyChangeListener l) {
        changes.removePropertyChangeListener(propertyName, l);
    }
    
    @Override
    public boolean cacheFilesValid () {
        return cacheloader.checkCacheFilesValid(doCatalogOnly);
    }
    
    
    protected void fireLater (String evtName) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                changes.firePropertyChange(evtName, false, null);
            }
        });
    }
    
}
