package usda.weru.remoteDataAccess;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import org.apache.commons.io.FileUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; 
import usda.weru.util.About;

/**
 *
 * @author mhaas
 */
abstract public class RdaInputControllerCachingSupport {
    protected File baseCacheDir;
    
    protected RdaInputController rdaController;
    protected RdaInterface rdaInterface;
    protected String interfaceName;
    
    public RdaInputControllerCachingSupport (RdaInputController controllerStatic) {
        
        rdaController = controllerStatic;
        rdaInterface = null;
        interfaceName = null;
        
        baseCacheDir = About.getWepsCacheDir();
    }
    
    public RdaInputController getController () {
        return rdaController;
    }
    
    public File getBaseCacheDir() {
        return baseCacheDir;
    }
    
    public void setBaseCacheDir(File newDir) {
        baseCacheDir = newDir;
        if (!baseCacheDir.exists()) {
            baseCacheDir.mkdirs();
        }
    }
    
    public void clearBaseCacheDir() {
        if (baseCacheDir.exists()) {
            try {
                FileUtils.deleteDirectory(baseCacheDir);
                baseCacheDir.mkdirs();
            } catch (IOException ex) {
            }
        }
    }
    
    public void setCacheSupportInterfaceName (String interfaceName) {
        this.interfaceName = interfaceName;
    }
    
    public boolean cacheWriteCatalog (ArrayList<String> catalog) throws IOException {
        return cacheWriteCatalog (catalog, false);
    }
    
    public boolean cacheWriteCatalog (ArrayList<String> catalog, boolean accumulate) throws IOException {
        
        boolean existsInCache = true;
        ArrayList<String> list = new ArrayList<>();

        baseCacheDir.mkdirs();
        String eol = System.lineSeparator();
        File catFile = new File (baseCacheDir, interfaceName+".catalog");
        
        // if accumulate, and value already there, exit
        if (catFile.exists()) {
            BufferedReader reader = new BufferedReader(new FileReader (catFile));
            String s;
            while ((s = reader.readLine()) != null) {
                list.add(s);
            }
            for (String name : catalog) {
                if (!list.contains(name)) {
                    existsInCache = false;
                }
            }
        } else {
            existsInCache = false;
        }
        
        if (!existsInCache) {
            FileWriter writer = new FileWriter (new File (baseCacheDir, interfaceName+".catalog"),accumulate);
            for (String name : catalog) {
                if ((!accumulate) || (accumulate && !list.contains(name))) {
                    writer.append(name+eol);
                }
            }
            writer.close();
        }
        return existsInCache;
    }
    
    public void cacheAddToCatalog (String pathStr) throws IOException {
        FileWriter writer = new FileWriter (new File (baseCacheDir, interfaceName+".catalog"), true);
        String eol = System.lineSeparator();
        
        writer.write(pathStr+eol);
        writer.close();
    }
    
    public ArrayList<String> cacheReadCatalog () throws IOException {
        FileReader reader = new FileReader (new File (baseCacheDir, interfaceName+".catalog"));
        String eol = System.lineSeparator();
        
        ArrayList<String> catalog = new ArrayList<>();
        int c;
        String s = "";
        
        while ((c = reader.read()) > -1) {
            if (eol.indexOf(c) > -1) {
                if (s.length() > 0) {
                    catalog.add(s);
                    s = "";
                }
            } else {
                s += (char)c;
            }
        }
        reader.close();
        
        return catalog;
    }
    
    public void checkAndClearCacheDir (int clrYr, int clrMo, int clrDay) {
                
        String fileTxt = "";
        boolean doClear = true;
        File dir = getBaseCacheDir();
        
        // Month is 0 based in Calendar
        GregorianCalendar specCal = new GregorianCalendar(clrYr, clrMo-1, clrDay);
        GregorianCalendar fileCal = null;
        String calTxt = specCal.get(Calendar.YEAR)+"-"+specCal.get(Calendar.MONTH)+"-"+specCal.get(Calendar.DAY_OF_MONTH);
        
        File cacheUpdateFile = new File (dir, "cacheClearLog.txt");
        if (cacheUpdateFile.exists()) {
            BufferedReader reader = null;
            try {
                reader = new BufferedReader (new InputStreamReader(new FileInputStream(cacheUpdateFile)));
                fileTxt = reader.readLine();
                if (fileTxt.length() > 0) {
                    String vals[] = fileTxt.split("-");
                    if (vals.length == 3) {
                        int yr = Integer.parseInt(vals[0]);
                        // Month is 0 based in Calendar
                        int mo = Integer.parseInt(vals[1])-1;
                        int day = Integer.parseInt(vals[2]);
                        fileCal = new GregorianCalendar(yr, mo, day);
                        if (specCal.before(fileCal)) {
                            doClear = false;
                        }
                    }
                }
            } catch (Exception ex) {
            }
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException ex) {
                }
            }
        }
        
        if (doClear) {
            LogManager.getLogger(this.getClass()).info("Clearing cache dir:"+
                    this.getBaseCacheDir().getAbsolutePath());
            LogManager.getLogger(this.getClass()).info("Clearing cache dir spec date:"+
                    specCal.get(Calendar.YEAR)+"-"+(specCal.get(Calendar.MONTH)+1)+"-"+specCal.get(Calendar.DAY_OF_MONTH));
            if (fileCal != null) {
                LogManager.getLogger(this.getClass()).info("Clearing cache dir file date:"+
                        fileCal.get(Calendar.YEAR)+"-"+(fileCal.get(Calendar.MONTH)+1)+"-"+fileCal.get(Calendar.DAY_OF_MONTH));
            } else {
                LogManager.getLogger(this.getClass()).info("Clearing cache dir file date not found:");
            }
            
            clearBaseCacheDir();
            
            BufferedWriter writer = null;
            try {
                writer = new BufferedWriter (new OutputStreamWriter(new FileOutputStream(cacheUpdateFile)));
                fileCal = new GregorianCalendar();
                // Month is 0 based in Calendar
                writer.write(fileCal.get(Calendar.YEAR)+"-"+(fileCal.get(Calendar.MONTH)+1)+"-"+fileCal.get(Calendar.DAY_OF_MONTH));
                writer.close();
            } catch (Exception ex) {
            }
            if (writer != null) {
                try {
                    writer.close();
                } catch (IOException ex) {
                }
            }
        }
    }

}
