package Main;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
import java.io.*;
import java.security.*;
import java.util.*;
/**
 *
 * @author phihai
 */
public class Chunks {
    
    public static long chunkSize = 512* 1024;
    		
    public void split(File f) throws FileNotFoundException, IOException // Cắt chunks
    {
        BufferedInputStream in = new BufferedInputStream(new FileInputStream(f));
        
        
        long fileSize = f.length();  
        int subfile;
        
        for (subfile = 0; subfile < fileSize / chunkSize; subfile++)
        {
            BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream("Share\\"+f.getName() + "." + subfile));

            for (int currentByte = 0; currentByte < chunkSize; currentByte++)
            {
                out.write(in.read());
            }
            out.close();           
        }
        if (fileSize != chunkSize * (subfile - 1))
        {          
            BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream("Share\\"+f.getName() + "." + subfile));
            int b;
            while ((b = in.read()) != -1)
                    out.write(b);
            out.close();          
        }
        in.close();
        Info_Chunk("Share\\"+f.getName());
    }

    public void join(String baseFilename) throws IOException // ghép chunks , basefilename là đường dẫn của tập tin
    {
        int numberParts = getNumberParts(baseFilename);

        BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(baseFilename));
        for (int part = 0; part < numberParts; part++)
        {
            BufferedInputStream in = new BufferedInputStream(new FileInputStream(baseFilename + "." + part));

            int b;
            while ( (b = in.read()) != -1 )
                    out.write(b);
            in.close();
        }
        out.close();
    }

    private static int getNumberParts(String baseFilename) throws IOException // đến số lượng chunks 
    {   
        File directory = new File(baseFilename).getAbsoluteFile().getParentFile();
        final String justFilename = new File(baseFilename).getName();
        String[] matchingFiles = directory.list(new FilenameFilter()
        {
            public boolean accept(File dir, String name)
            {
                return name.startsWith(justFilename) && name.substring(justFilename.length()).matches("^\\.\\d+$");
            }
        });
        return matchingFiles.length;
    }
    
    public String[] getFileName(String dirname) throws IOException // lấy tên các tập tin có thể download từ file (filename.chunk)
    {   
        File directory = new File(dirname);
        
        String[] matchingFiles = directory.list(new FilenameFilter()
        {
            public boolean accept(File dir, String name)
            {
                return name.endsWith(".chunk");
            }
        });
        return matchingFiles;
    }
    
    public void Info_Chunk(String baseFilename) throws IOException // xuất thông tin file + mã hash của tập tin vào file filenamme.chunks
    {
        String str;
        int numberParts = getNumberParts(baseFilename);
        File file = new File(baseFilename + "."+"chunk");
        BufferedWriter out = new BufferedWriter(new FileWriter(file));
             
        for (int part = 0; part < numberParts; part++)
        {
            str = part + " " + hash(baseFilename + "." + part) + "\r\n";
            out.write(str);           
        }
        out.close();
        System.out.print(file.getName() +" đã được tạo \n");
    }
    
//    public String List_Chunk(String baseFilename) throws IOException
//    { 
//        File directory = new File(baseFilename).getAbsoluteFile().getParentFile();
//        final String justFilename = new File(baseFilename).getName();
//        String[] matchingFiles = directory.list(new FilenameFilter()
//        {
//            public boolean accept(File dir, String name)
//            {
//                return name.startsWith(justFilename) && name.substring(justFilename.length()).matches("^\\.\\d+$");
//            }
//        });
//        
//        List<String> list = getHash(justFilename+".chunk");
//        String str = "";
//       
//        for (int part = 0; part < matchingFiles.length; part++)
//        {              
//            if(list.contains(hash(matchingFiles[part])))
//            {
//                str += matchingFiles[part] + "\r\n";
//            }
//        }       
//        return str;
//    }
    
    public List<String> List_Chunk(String baseFilename) throws IOException // Lay danh sach Hash cua cac file hien co trên client thực thi
    {      
        File directory = new File(baseFilename).getAbsoluteFile().getParentFile();       
        final String justFilename = new File(baseFilename).getName();
        String[] matchingFiles = directory.list(new FilenameFilter()
        {
            public boolean accept(File dir, String name)
            {
                return name.startsWith(justFilename) && name.substring(justFilename.length()).matches("^\\.\\d+$");
            }
        });
        
        List<String> list = new ArrayList<String>(); 
          
        for (int part = 0; part < matchingFiles.length; part++)
        {              
            list.add(hash("Share\\"+matchingFiles[part]));
        }       
        return list;
    }
    public String Check_Chunks(String hashChunks) // nhận thông tin mã hash từ client thực thi, client nhận hash sẽ tiến hành kiểm tra tồn tại của file thông qua mã hash này
    {
        String temp = "";
        File folder = new File("Share\\");
        File[] listOfFiles = folder.listFiles();
        for(int i=0;i<listOfFiles.length;i++)
        {
            if(listOfFiles[i].isFile())
            {               
                if(hash(listOfFiles[i].getAbsolutePath()).equals(hashChunks))
                {
                    temp = listOfFiles[i].getName();
                    break;
                }
            }
        }
        return temp;
    }
//    public List<String> Find_Chunks(String baseFilename) // Tim cac chunks chua co
//    { 
//        List<String> listFile = new ArrayList<String>();
//        final String justFilename = new File(baseFilename).getName();
//        try
//        {
//            String str ;
//            List<String> list = List_Chunk(baseFilename); 
//            
//            BufferedReader br = new BufferedReader(new FileReader(justFilename+".chunk"));  
//            System.out.print("Cac Chunk còn thiếu:\n");
//            while ((str = br.readLine()) != null)
//            {		                    				
//                String []array = str.split(" "); 
//                if(!list.contains(array[1]))
//                {
//                    listFile.add(array[1]);
//                    System.out.print(array[0]+"\n");
//                }                         
//            }
//        }        
//        catch (Exception e)
//        {
//            e.printStackTrace();
//        }
//        return listFile;
//    }
    
//    private static List<String> getHash(String Filename)
//    {
//        List<String> list = new ArrayList<String>();       
//        try
//        {
//            String str ;
//            
//            BufferedReader br = new BufferedReader(new FileReader(Filename));                    
//            while ((str = br.readLine()) != null)
//            {		                    				
//                String []array = str.split(" ");               
//                list.add(array[1]);           
//            }             
//        }        
//        catch (Exception e)
//        {
//            e.printStackTrace();
//        }
//        return list;
//    }
    
    public static String hash(String filename) // filename đường dẫn của file, lấy thông tin của file hash ra mã SHA-1
    {
        String result = "";
        try
        {
            BufferedInputStream in = new BufferedInputStream(new FileInputStream(filename));
            MessageDigest md = MessageDigest.getInstance("SHA-1");
            byte [] buffer = new byte[1024];
            int sizeRead;
            while ((sizeRead = in.read(buffer)) != -1) 
            {
                md.update(buffer, 0, sizeRead);
            }
            in.close();

            byte [] hash = md.digest();
          
            for (int i=0; i < hash.length; i++) {
                result += Integer.toString( ( hash[i] & 0xff ) + 0x100, 16).substring( 1 );
            }
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
        }
        return result;
    }
}
