package com.qiyou.mb.android.utils;

import java.io.*;

import org.apache.http.util.EncodingUtils;

import android.content.Context;

import com.facebook.crypto.Crypto;
import com.facebook.crypto.Entity;
import com.facebook.crypto.exception.CryptoInitializationException;
import com.facebook.crypto.exception.KeyChainException;
import com.qiyou.mb.android.utils.log.QLog;
 
/**
 * @author Toby 复制文件夹或文件夹
 */
public class FileUtil { 
	public static final String TAG = "com.qiyou.mb.android.utils.FileUtil";
	public static final String dTAG = "com.qiyou";
    // 复制文件
    public static void copyFile(File sourceFile, File targetFile) throws IOException {
        BufferedInputStream inBuff = null;
        BufferedOutputStream outBuff = null;
        try {
            // 新建文件输入流并对它进行缓冲
            inBuff = new BufferedInputStream(new FileInputStream(sourceFile));

            // 新建文件输出流并对它进行缓冲
            outBuff = new BufferedOutputStream(new FileOutputStream(targetFile));

            // 缓冲数组
            byte[] b = new byte[1024 * 5];
            int len;
            while ((len = inBuff.read(b)) != -1) {
                outBuff.write(b, 0, len);
            }
            // 刷新此缓冲的输出流
            outBuff.flush();
        } finally {
            // 关闭流
            if (inBuff != null)
                inBuff.close();
            if (outBuff != null)
                outBuff.close();
        }
    }

    // 复制文件夹
    public static void copyDirectiory(String sourceDir, String targetDir) throws IOException {
        // 新建目标目录
        (new File(targetDir)).mkdirs();
        // 获取源文件夹当前下的文件或目录
        File[] file = (new File(sourceDir)).listFiles();
        for (int i = 0; i < file.length; i++) {
            if (file[i].isFile()) {
                // 源文件
                File sourceFile = file[i];
                // 目标文件
                File targetFile = new File(new File(targetDir).getAbsolutePath() + File.separator + file[i].getName());
                copyFile(sourceFile, targetFile);
            }
            if (file[i].isDirectory()) {
                // 准备复制的源文件夹
                String dir1 =sourceDir.endsWith(File.separator)?(sourceDir + file[i].getName()): (sourceDir + "/" + file[i].getName());
                // 准备复制的目标文件夹
                String dir2 = targetDir.endsWith(File.separator)?(targetDir + file[i].getName()): (targetDir + "/" + file[i].getName());  
                copyDirectiory(dir1, dir2);
            }
        }
    }

    /**
     * 
     * @param srcFileName
     * @param destFileName
     * @param srcCoding
     * @param destCoding
     * @throws IOException
     */
    public static void copyFile(File srcFileName, File destFileName, String srcCoding, String destCoding) throws IOException {// 把文件转换为GBK文件
        BufferedReader br = null;
        BufferedWriter bw = null;
        try {
            br = new BufferedReader(new InputStreamReader(new FileInputStream(srcFileName), srcCoding));
            bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(destFileName), destCoding));
            char[] cbuf = new char[1024 * 5];
            int len = cbuf.length;
            int off = 0;
            int ret = 0;
            while ((ret = br.read(cbuf, off, len)) > 0) {
                off += ret;
                len -= ret;
            }
            bw.write(cbuf, 0, off);
            bw.flush();
        } finally {
            if (br != null)
                br.close();
            if (bw != null)
                bw.close();
        }
    }

    /**
     * 
     * @param filepath
     * @throws IOException
     */
    public static void del(String filepath) throws IOException {
        File f = new File(filepath);// 定义文件路径
        if (f.exists() && f.isDirectory()) {// 判断是文件还是目录
            if (f.listFiles().length == 0) {// 若目录下没有文件则直接删除
                f.delete();
            } else {// 若有则把文件放进数组，并判断是否有下级目录
                File delFile[] = f.listFiles();
                int i = f.listFiles().length;
                for (int j = 0; j < i; j++) {
                    if (delFile[j].isDirectory()) {
                        del(delFile[j].getAbsolutePath());// 递归调用del方法并取得子目录路径
                    }
                    delFile[j].delete();// 删除文件
                }
            }
        }
    }
    
    final static String DELICODES="ThisIs->DELICOD@$&*S?>";
    public static void writeFile(Crypto crypto,Entity entity,String fileName,String plainText ) throws IOException, CryptoInitializationException, KeyChainException{
    	// Creates a new Crypto object with default implementations of 
    	// a key chain as well as native library.
    	/*Crypto crypto = new Crypto(
    	  new SharedPrefsBackedKeyChain(context),
    	  new SystemNativeCryptoLibrary());
	    entity = new Entity("TEST");*/
    	// Check for whether the crypto functionality is available
    	// This might fail if android does not load libaries correctly.
    	if (!crypto.isAvailable()) {
    		QLog.getLogger().d(dTAG, "crypto is not available");
    	  return;
    	}
    	QLog.getLogger().d(dTAG, "crypto is available");
    	 File file = new File(fileName); 

    	OutputStream fileStream = new BufferedOutputStream(
    	  new FileOutputStream(file));

    
    	
    	
    	// Creates an output stream which encrypts the data as
    	// it is written to it and writes it out to the file.
    	OutputStream outputStream = crypto.getCipherOutputStream(
    	  fileStream,
    	  entity);
  
//    	plainTextBytes =(plainText+DELICODES).getBytes();
    	
    	// Write plaintext to it.
    	outputStream.write((plainText+DELICODES).getBytes());
    	
    	outputStream.close();
    	QLog.getLogger().d(dTAG, " crypto encrypts successfully...........");
    }
    
    public static String  readFile(String fileName,Crypto crypto,Entity entity){
    	
    	if (!crypto.isAvailable()) {
      	  return null;
      	}
    	
    	File file = new File(fileName);
        
        if(!file.exists()) return null;
        String res=null;
    	// Get the file to which ciphertext has been written.
    	FileInputStream fileStream;
		try {
			fileStream = new FileInputStream(file);
		

    	// Creates an input stream which decrypts the data as
    	// it is read from it.
    	InputStream inputStream = crypto.getCipherInputStream(
    	  fileStream,
    	  entity);
    	

        int length = inputStream.available(); 

         byte [] buffer = new byte[length]; 
         inputStream.read(buffer);     
         
         
         File file2 = new File(fileName+"_dd");  

         FileOutputStream fos = new FileOutputStream(file2);  
//         FileOutputStream fos1 = new FileOutputStream(file, isAppend) ; 
         fos.write(buffer);  
         fos.close(); 
         

        res = EncodingUtils.getString(buffer, "UTF-8"); 

         inputStream.close();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (CryptoInitializationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (KeyChainException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
         return res;  
         
/*
    	// Read into a byte array.
    	int read;
    	byte[] buffer = new byte[1024];

    	// You must read the entire stream to completion.
    	// The verification is done at the end of the stream.
    	// Thus not reading till the end of the stream will cause
    	// a security bug. 
    	while ((read = inputStream.read(buffer)) != -1) {
    	 
    	}

    	inputStream.close();
    	*/
    	  
    }
    
    public static void encodeFile(String encryptedFileName,String plainedFileName,Crypto crypto,Entity entity){

    	File mEncryptedFile = new File(encryptedFileName);
    	File mPlainFile = new File(plainedFileName); 
//        if(!mEncryptedFile.exists()) return null;
//        String res=null;
    	
    	if (!crypto.isAvailable()) {
    		QLog.getLogger().d(dTAG, "crypto is not available...........................");
    	  return;
    	}
    	
        try{
	    	BufferedOutputStream fileStream = new BufferedOutputStream(new FileOutputStream(mEncryptedFile));
//        	BufferedOutputStream fileStream = new BufferedOutputStream(new FileOutputStream(mPlainFile));
	    	OutputStream outputStream;
	    	outputStream = crypto.getCipherOutputStream(fileStream, entity);
	    	int read;
	    	byte[] buffer = new byte[1024];
	    	BufferedInputStream  bis = new BufferedInputStream(new FileInputStream(mPlainFile));
	    	while ((read = bis.read(buffer)) != -1) {
	    	       outputStream.write(buffer, 0, read);
	    	    }
	    	outputStream.close();
	    	bis.close();
 	    	mPlainFile.delete();
	    	QLog.getLogger().d(dTAG, " EnCoded from "+plainedFileName+".................");
        }catch(IOException ioe){
    		Utils.logStackTrace(ioe, TAG);
    	} catch (CryptoInitializationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (KeyChainException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    }
    
    
    public static void decodeFile(String encryptedFileName,String plainedFileName,Crypto crypto,Entity entity){

    	File mEncryptedFile = new File(encryptedFileName);
    	File mDecryptedFile = new File(plainedFileName); 
         if(!mEncryptedFile.exists()) {
        		QLog.getLogger().d(dTAG,encryptedFileName+ " dose not exist ");
        	 return  ;
         }
         if (!crypto.isAvailable()) {
     		QLog.getLogger().d(dTAG, "crypto is not available......................");
     	  return;
     	}
        try{
        	InputStream inputStream;
        	FileInputStream fileStream = new FileInputStream(mEncryptedFile);
        	inputStream = crypto.getCipherInputStream(fileStream, entity);
        	ByteArrayOutputStream out = new ByteArrayOutputStream();
        	OutputStream outputStream = new FileOutputStream(mDecryptedFile);
        	BufferedInputStream bis = new BufferedInputStream(inputStream);
        	int mRead;
        	byte[] mBuffer = new byte[1024];
        	while ((mRead = bis.read(mBuffer)) != -1) {
        	   outputStream.write(mBuffer, 0, mRead);
        	    }
        	bis.close();
        	out.writeTo(outputStream);
        	inputStream.close();
        	outputStream.close();
        	out.close();
        	QLog.getLogger().d(dTAG, " deCoded from "+encryptedFileName+".................");
        }catch(IOException ioe){
    		Utils.logStackTrace(ioe, TAG);
    	} catch (CryptoInitializationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (KeyChainException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    }
    
    public static String readEncodedFile(String fileName,   Crypto crypto,Entity entity){
    	String tmpFileName =fileName+"tmp";
    	String ret=null;
    	
    	QLog.getLogger().d(dTAG, " begin to decode File "+fileName+"..............");
    	
    	decodeFile(fileName,tmpFileName,crypto,  entity);
    	
//    	QLog.getLogger().d(dTAG, " begin to read from decoded File "+tmpFileName+"..............");
    	try{
    	 ret = Utils.readSDFile(tmpFileName);
    	 
//    	 QLog.getLogger().d(dTAG, " readed content is "+ret+"..............");
    	 File tmp = new File(tmpFileName);
    	 tmp.delete();
    	
    	}catch(IOException e){
    		Utils.logStackTrace(e, TAG);
    	}
    	catch(Exception e){
    		Utils.logStackTrace(e, TAG);
    	} 
    	
    	return ret;
    	
    }
			  
		     
    
    
    
}