
package usda.weru.remoteDataAccess.remoteFiles;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Objects;
import javax.swing.JOptionPane;
import javax.swing.ProgressMonitor;
import usda.weru.remoteDataAccess.RdaHierarchicalItem;
import usda.weru.remoteDataAccess.RdaInputController;
import usda.weru.remoteDataAccess.exceptions.RdaConnectException;
import static usda.weru.util.Util.getProperty;

/**
 *
 * @author mhaas
 */
public class RemoteFile extends WepsBaseFile  {
    
    static final long serialVersionUID = 1L;

    public enum RemoteFileType {
        FILE,
        INET,
        LMOD,
        CRLMOD,
        DB,
        SOILS,
        PRISM
    }
    protected RdaInputController controller;
    protected RdaHierarchicalItem controllerItem = null;
    
    protected String name;
    protected RemoteFile parent;   
    protected RemoteFileType type;
    
    protected Path destinationPath;

    public RemoteFile() {
        this("", RemoteFileType.FILE);
//        System.out.println("blank constructor");
    }

    public RemoteFile(String name) {
        this(name, RemoteFileType.FILE);
//        System.out.println("name constructor");
    }

    public RemoteFile(String name, RemoteFileType type) {
        super(name);
        destinationPath = Paths.get(getProperty("project.directory"));

        this.type = type;
        if (type == RemoteFileType.FILE) {
            this.name = super.getName();
            this.parent = (RemoteFile) getParentFile();
        } else {
            this.name = name;
            this.parent = null;
        }
//        System.out.println("RemoteFile Name: " + name);
//        System.out.println("RemoteFile Type: " + type.name());
//        System.out.println("RemoteFile Path: " + getAbsolutePath());
//        if(parent != null) {
//            System.out.println("RemoteFile Parent: " + parent.name);
//        } else {
//            System.out.println("RemoteFile Parent: null");
//        }
        controller = null;
        controllerItem = null;
//        System.out.println("name/type constructor");
    }

    public RemoteFile(String parent, String name, RemoteFileType type) {
        this(new RemoteFile(parent, type), name);
//        System.out.println("parent/name/type constructor");
    }

    public RemoteFile(RemoteFile parent, String name) {
        super(parent, name);
        destinationPath = Paths.get(getProperty("project.directory"));
        // MEH
        this.type = parent.type;
        this.name = name;
        this.parent = parent;

        controller = parent.controller;
        if (parent.controllerItem != null) {
            controllerItem = parent.controllerItem.getChild(name);
        }
//        System.out.println("RemoteFile Name: " + name);
//        System.out.println("RemoteFile Type: " + type.name());
//        System.out.println("RemoteFile Path: " + getAbsolutePath());
//        System.out.println("Parent Path: " + parent.getAbsolutePath());
//        System.out.println("Parent Name: " + parent.getName());

    }

    public void setDestinationPath(Path destPath) {
        destinationPath = destPath;

        if (controllerItem != null) {
            controllerItem.setDestinationPath(destPath);
        }
    }

    // force / prompt controller to re-load remote data.
    public void reInitialize() {
        // re-setting to null will force to re-initialize in listFiles
        controllerItem = null;
    }
    
    // removed message dialog for now - EL 09/16/21
    public File downloadFile() throws IOException {      
        try {
            System.out.println("RemoteFile.java - ControllerItem parent path: " + controllerItem.getParentPath());
            return controllerItem.getItemData();
        } catch (RdaConnectException ex) {
            System.err.println("Error downloading file from remote service: " + ex.getServiceName() + ". Reason : "
                    + "Result file invalid.\n See - RemoteFile.java:119:downloadFile()");
//            JOptionPane.showMessageDialog(null, "Error downloading file from remote service: " + ex.getServiceName() + "\n\n"
//                    + "Result file invalid.", "Connection Error", JOptionPane.ERROR_MESSAGE);
            throw new IOException ("No result file at parent path - " + controllerItem.getParentPath());
       }
    }

    public File downloadFile(ProgressMonitor progress) throws IOException {
        try {
            return controllerItem.getItemData(progress);
        } catch (RdaConnectException ex) {
            JOptionPane.showMessageDialog(null, "Error downloading file from remote service: " + ex.getServiceName() + "\n\n"
                    + "Result file invalid.", "Connection Error", JOptionPane.ERROR_MESSAGE);
            throw new IOException("No result file at parent path - " + controllerItem.getParentPath());
        }
    }

    @Override
    public String getParent() {
        return parent == null ? null : parent.getAbsolutePath();
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public File getParentFile() {
        return parent;
    }

    @Override
    public String getAbsolutePath() {
        if (parent != null) {
            return parent.getAbsolutePath() + "/" + name;
        } else {
            return name;
        }
    }

    @Override
    public String getCanonicalPath() {
        return getAbsolutePath();
    }

    @Override
    public boolean isDirectory() {
        return !isFile();
    }

    @Override
    public boolean isFile() {

        // If this is a disk file, use TFile so that we can descend into zips, etc.
        if (type == RemoteFileType.FILE) {
            return super.isFile();
        } else {
            if (controllerItem != null) {
                return controllerItem.isFile();
            } else {
                return false;
            }
        }
    }

    public RemoteFileType getType() {
        return type;
    }

    @Override
    public File[] listFiles() {
        return listFiles((FileFilter) null);
    }

    @Override
    public File[] listFiles(FileFilter filter) {
        ArrayList<File> retVal = new ArrayList<>();

        if (controllerItem == null && controller != null) {
            try {
                controllerItem = controller.init(name);
                controllerItem.setDestinationPath(destinationPath);
            } catch (RdaConnectException ex) {
                controllerItem = controller.getRootItem();
                JOptionPane.showMessageDialog(null, "Unable to connect/communicate to remote service:" + ex.getServiceName() + "\n\n"
                        + "Verify your internet connection is working.", "Connection Error", JOptionPane.ERROR_MESSAGE);
            }
        }

        ArrayList<String> fNames = controller.getPathItems(controllerItem);
        Collections.sort(fNames);
        for (String s : fNames) {
            File f = WepsBaseFile.newOfParentType(this, s);
            if (filter == null || filter.accept(f)) {
                retVal.add(f);
            }
        }
        return retVal.toArray(new File[0]);
    }

    @Override
    public boolean equals(Object obj) {
        boolean ret = false;
        if (obj instanceof RemoteFile) {
            if (((RemoteFile) obj).name.equals(name)) {
                if (parent == null) {
                    // if names equal and there is no parent, good enough, return true
                    return true;
                } else if (((RemoteFile) obj).parent.equals(parent)) {
                    // (This .equals call above is recursive ... )
                    // if there is a parent, and parent are also equal, return true;
                    ret = true;
                }
            }
        }
        return ret;
    }

    @Override
    public int hashCode() {
        int hash = 5;
        hash = 71 * hash + Objects.hashCode(getType());
        return hash;
    }
}
