package uk.ac.reload.editor.upload;

import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;
import com.jcraft.jsch.UserInfo;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FilterInputStream;
import java.io.IOException;
import java.net.UnknownHostException;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JLabel;
import javax.swing.JProgressBar;

import org.apache.commons.net.ftp.FTPConnectionClosedException;

/**
 *
 * @author Gonzalo
 */
public class UploadTask implements ProgressListener {

    private File basePath;
    private Vector<File> filesVector;
    private Vector<File> dirsVector;
    private String host;
    private String userName;
 private static String password;
    private String ftpPath;
    private JProgressBar jpbGlobal;
    private JProgressBar jpbFile;
    private JLabel jLabelPercentage;
    private JLabel jLabelBytesFileProgress;
    private JLabel jLabelUploading;
    private String currentFileSizeKB;
    private String totalSizeKB;
    private String defaultRepository;

    public UploadTask() {
    }

    public UploadTask(File basePath, String ftpAddress, String ftpUser, String ftpPassword, String ftpPath, JProgressBar jpbGlobal, JProgressBar jpbFile, JLabel jl, JLabel jl2, JLabel jLabelUploading, String defaultRepository) {
        this.basePath = basePath;
        this.host = ftpAddress;
        this.userName = ftpUser;
        this.password = ftpPassword;
        this.jpbGlobal = jpbGlobal;
        this.jpbFile = jpbFile;
        this.ftpPath = ftpPath;
        this.jLabelPercentage = jl;
        this.jLabelBytesFileProgress = jl2;
        this.jLabelUploading = jLabelUploading;
        this.defaultRepository=defaultRepository;

        /*for (File file : this.basePath.listFiles()) {
            System.out.println(file.getName() + (file.isDirectory() ? "<dir>" : "<file>"));
        }*/
        filesVector = readFiles(this.basePath);
        dirsVector = readDirs(this.basePath);
    }

    public long getTotalSize() {
        long size = 0;
        for (File file : filesVector) {
            size += file.length();
        }
        return size;
    }

    public File nextFile() {
        if (!filesVector.isEmpty()) {
            return filesVector.remove(0);
        } else {
            return null;
        }
    }

    public int countFiles() {
        //System.out.println("**Contando el número de archivos**");
        return countFiles(this.basePath);
    }

    private int countFiles(File baseDir) {
        int numFiles = 0;
        File[] fileList = baseDir.listFiles();
        for (File file : fileList) {
            if (file.isDirectory()) {
                numFiles += countFiles(file);
            } else if (!file.isHidden()) {
                System.out.println("> " + file.getPath());
                numFiles++;
            }
        }
        return numFiles;
    }

    private Vector<File> readFiles(File baseDir) {
        Vector<File> vFiles = new Vector<File>();
        File[] fileList = baseDir.listFiles();
        for (File file : fileList) {
            if (file.isDirectory()) {
                vFiles.addAll(readFiles(file));
            } else if (!file.isHidden()) {
                vFiles.add(file);
            }
        }
        return vFiles;
    }

    private Vector<File> readDirs(File baseDir) {
        Vector<File> vDirs = new Vector<File>();
        File[] fileList = baseDir.listFiles();
        for (File file : fileList) {
            if (file.isDirectory()) {
                vDirs.add(file);
                //System.out.println(">>>>>>> Añado el directorio "+file.getName());
                vDirs.addAll(readDirs(file));
            }
        }
        return vDirs;
    }

    public void execute() throws InterruptedException {

         File file;
      

        JSch jsch = new JSch();
        Session session = null;
        ChannelSftp chan = null;
        try {
            session = jsch.getSession(userName, host, 22);

            session.setPassword(password);

            UserInfo usrInfo = new MyUserInfo();

            session.setUserInfo(usrInfo);
            session.connect();

            chan = (ChannelSftp) session.openChannel("sftp");

            chan.connect();

             if (defaultRepository.equals("Osami")) {
            chan.cd("apache-tomcat-6.0.20/webapps/Courses/osami/" + this.ftpPath);
             }
             if (defaultRepository.equals("Cesga")) {
            chan.cd("apache-tomcat-6.0.20/webapps/Courses/cesga/" + this.ftpPath);
             }
             if (defaultRepository.equals("Suma")) {
            chan.cd("apache-tomcat-6.0.20/webapps/Courses/suma/" + this.ftpPath);
             }
            System.out.println(chan.pwd());

        } catch (JSchException ex) {
            Logger.getLogger(UploadTask.class.getName()).log(Level.SEVERE, null, ex);
        } catch (SftpException ex) {
            Logger.getLogger(UploadTask.class.getName()).log(Level.SEVERE, null, ex);
        }

        long totalSize = getTotalSize();
        jpbGlobal.setMaximum((int) totalSize);
        totalSizeKB = String.valueOf(totalSize / 1024);
        jpbGlobal.setValue(0);
        jLabelPercentage.setText("0/" + totalSizeKB + " KB");

        makeFtpDirs(chan);

        //Creamos los directorios necesarios en el servidor ftp

        //Subimos cada fichero indivualmente
        while ((file = nextFile()) != null) {
            jpbFile.setMaximum((int) file.length());
            jpbFile.setValue(0);
            currentFileSizeKB = String.valueOf(file.length() / 1024);
            jLabelBytesFileProgress.setText("0/" + currentFileSizeKB + " KB");
            FileProgressMonitorInputStream fpmis = null;
            try {
                fpmis = new FileProgressMonitorInputStream(new FileInputStream(file), this);
            } catch (FileNotFoundException ex) {
                Logger.getLogger(UploadTask.class.getName()).log(Level.SEVERE, null, ex);
            }
            String fileRelativePath = file.getPath().replace(this.basePath.getPath(), "").substring(1);

            jLabelUploading.setText("Uploading: " + fileRelativePath);
            try {

                String[] directories = fileRelativePath.split("\\\\");
                for (String s : directories) {
                    //System.out.println("**** " + s);
                }

                chan.put(fpmis, fileRelativePath.replaceAll("\\\\", "/"));

            } catch (SftpException ex) {
                Logger.getLogger(UploadTask.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        chan.disconnect();

        session.disconnect();

        //HUbo que cambiarlo pq ahora es un servidor SFTP

        /*
        try {
            JakartaFtpWrapper ftp = new JakartaFtpWrapper();
            File file;
            //Nos conectamos al servidor FTP
            ftp.connectAndLogin(host, userName, password);
            ftp.setPassiveMode(true);
            //Cambiamos al directorio donde vamos a almacenar el curso
            //System.out.println(this.ftpPath);
            //System.out.println(ftp.changeWorkingDirectory(this.ftpPath));
            ftp.changeWorkingDirectory(this.ftpPath);
            long totalSize = getTotalSize();
            jpbGlobal.setMaximum((int) totalSize);
            totalSizeKB = String.valueOf(totalSize / 1024);
            jpbGlobal.setValue(0);
            jLabelPercentage.setText("0/"+totalSizeKB+ " KB");
            //System.out.println(ftp.uploadFile("c:\\Prueba.java", "uno/dos/boot.txt"));
            //System.out.println(ftp.makeDirectory("uno/dos"));
            //Thread.sleep(5000);
            //Creamos los directorios necesarios en el servidor ftp
            makeFtpDirs(ftp);
            //Subimos cada fichero indivualmente
            while ((file = nextFile()) != null) {
                jpbFile.setMaximum((int) file.length());
                jpbFile.setValue(0);
                currentFileSizeKB = String.valueOf(file.length() / 1024);
                jLabelBytesFileProgress.setText("0/"+currentFileSizeKB+" KB");
                FileProgressMonitorInputStream fpmis = new FileProgressMonitorInputStream(new FileInputStream(file), this);
                String fileRelativePath = file.getPath().replace(this.basePath.getPath(), "").substring(1);
                //System.out.println(fileRelativePath);
                //jLabelUploading.setText("Uploading: " + file.getName());
                jLabelUploading.setText("Uploading: " + fileRelativePath);
                if (file.getName().endsWith(".xml") || file.getName().endsWith(".xsd")) {
                    ftp.ascii();
                } else {
                    ftp.binary();
                }
                if (Thread.interrupted()) {
                    System.out.println("El hilo fue INTERRUMPIDO");
                    ftp.logout();
                    ftp.disconnect();
                    throw new InterruptedException("Upload interrupted");
                } else {
                    //System.out.println("El hilo no fue interrumpido");
                }
                //System.out.println(this.basePath.getPath());
                               
              
                //ftp.storeFile(file.getName(), fpmis);
                ftp.storeFile(fileRelativePath.replaceAll("\\\\", "/"), fpmis);
            }
            ftp.logout();
            ftp.disconnect();
        } catch (UnknownHostException ex) {
            ex.printStackTrace();
        } catch (FTPConnectionClosedException ex) {
            ex.printStackTrace();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        */
    }

    public void progressUpdated(long readBytes) {
        jpbFile.setValue(jpbFile.getValue() + (int) readBytes);
        jpbGlobal.setValue(jpbGlobal.getValue() + (int) readBytes);
        //jLabelPercentage.setText(jpbGlobal.getString());
        jLabelPercentage.setText(jpbGlobal.getValue()/1024+"/"+totalSizeKB+ " KB");
        jLabelBytesFileProgress.setText(jpbFile.getValue()/1024+"/"+currentFileSizeKB+" KB");
    }



     private void makeFtpDirs(ChannelSftp ftp) {
        for (File dir : this.dirsVector) {
            String dirRelativeName = dir.getPath().replace(this.basePath.getPath(), "").substring(1);
            dirRelativeName = dirRelativeName.replaceAll("\\\\", "/");


            try {
                //System.out.println("###########************ "+dirRelativeName);
                ftp.mkdir(dirRelativeName);

            } catch (SftpException ex) {
                Logger.getLogger(UploadTask.class.getName()).log(Level.SEVERE, null, ex);
            }


        }


    }

    //ahora distinto
    private void makeFtpDirs(JakartaFtpWrapper ftp) throws IOException {
        for (File dir : this.dirsVector)  {
            String dirRelativeName = dir.getPath().replace(this.basePath.getPath() , "").substring(1);
            dirRelativeName = dirRelativeName.replaceAll("\\\\", "/");
            //System.out.println("###########************ "+dirRelativeName);
            ftp.makeDirectory(dirRelativeName);
        }
    }

    public class FileProgressMonitorInputStream extends FilterInputStream {

        ProgressListener pl;

        public FileProgressMonitorInputStream(FileInputStream fis, ProgressListener pl) {
            super(fis);
            this.pl = pl;
        }

        public int read(byte b[], int off, int len) throws IOException {
            // public int read(byte b[]) throws IOException {

            int nr = in.read(b, off, len); // read from the underlying stream
            if (nr > 0) {
                pl.progressUpdated(nr);
            }
            return nr;
        }
        public int read(byte b[]) throws IOException {
            int nr = in.read(b); // read from the underlying stream
            if (nr > 0) {
                pl.progressUpdated(nr);
            }
            return nr;
        }
    }
    public static void main(String[] args) {
        String ruta = "C:\\programas\\miprograma";
        String rutaUnix = "/home/gonzalo/programa";
        System.out.println(ruta);
        System.out.println(ruta.replaceAll("\\\\", "/"));
        System.out.println(rutaUnix.replaceAll("\\\\", "/"));
    }

     public static class MyUserInfo implements UserInfo {

        public String getPassword() {
            return password;
        }

        public String getPassphrase() {
            return "";
        }

        public boolean promptPassword(String arg0) {
            return true;
        }

        public boolean promptPassphrase(String arg0) {
            return true;
        }

        public boolean promptYesNo(String arg0) {
            return true;
        }

        public void showMessage(String arg0) {

        }
     }

}
