package com.zzsn.util;

import java.io.*;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class FileUtil {
	
	public static List<String> getFileLines(File file, String encoding) 
			throws IOException
	{
		List<String> lines = new ArrayList<String>();
		if (encoding == null)
		{
			encoding = "utf-8";
		}
		FileInputStream stream = new FileInputStream(file);
		InputStreamReader reader = new InputStreamReader(stream, encoding);
		BufferedReader bufferedReader = new BufferedReader(reader);
		String line = null;
		while ((line = bufferedReader.readLine()) != null)
		{
			lines.add(line);
		}
		bufferedReader.close();
		reader.close();
		stream.close();
		return lines;
	}
	public static void outMsg(String fileName, String content) {
		

		File files = new File(fileName);
		FileWriter writer = null;
		try {
			if (!files.exists()) {
				files.createNewFile();
			}
			// 打开一个写文件器，构造函数中的第二个参数true表示以追加形式写文件
			writer = new FileWriter(files, true);
			writer.write(content);
			writer.write("\n");
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if(writer != null){
					writer.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	public static String getFileBody(File file, String encoding)
	{
		StringBuffer buffer = new StringBuffer();
		try {
			List<String> lines = getFileLines(file, encoding);
			for (String line : lines)
			{
				buffer.append(line);
				buffer.append("\n");
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		return buffer.toString();
	}

	public static String getFileBody(String path, String encoding)
	{
		File file = new File(path);
		if (!file.exists())
		{
			return null;
		}
		return getFileBody(file, encoding);
	}
	
	public static void mergeFile(String dir, int depth, 
			String outPath, String encoding)
	{
		File dirFile = new File(dir);
		List<File> filesForMerge = collectFiles(dirFile, depth, -1);
		StringBuffer buffer = new StringBuffer();
		for (File file : filesForMerge)
		{
			String temp = getFileBody(file, encoding);
			buffer.append(temp);
			buffer.append("\n");
		}
		try {
			PrintWriter pw = new PrintWriter(outPath);
			pw.write(buffer.toString());
			pw.close();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public static List<File> collectFiles(File dirFile, int depth, int sampleNum)
	{
		List<File> filesForMerge = new ArrayList<File>();
		if (1 == depth)
		{
			
			File[] subFiles = dirFile.listFiles();
			for (File file : subFiles)
			{
				if (file.isDirectory())
				{
					continue;
				}
				filesForMerge.add(file);
			}
			filesForMerge = sampleFiles(filesForMerge, sampleNum);
		}
		else 
		{
			File[] subFiles = dirFile.listFiles();
			for (File file : subFiles)
			{
				if (!file.isDirectory())
				{
					continue;
				}
				List<File> files = collectFiles(file, depth-1, sampleNum);
				if (files.size() > 0)
				{
					filesForMerge.addAll(files);
				}			
			}	
		}		
		return filesForMerge;
	}
	
	private static List<File> sampleFiles(List<File> origFiles, int sampleNum)
	{
		List<File> sampleFiles = new ArrayList<File>();
		int totalSize = origFiles.size();
		if (sampleNum >= 0 && totalSize > sampleNum)
		{
			if (sampleNum < totalSize / 10)
			{
				sampleNum = totalSize / 10;
			}
			Random random = new Random();
			int count = 0;
			while (count < sampleNum)
			{
				int pos = random.nextInt(totalSize);
				File nextFile = origFiles.get(pos);
				if (sampleFiles.contains(nextFile))
				{
					continue;
				}
				sampleFiles.add(nextFile);
				count ++;
			}
			return sampleFiles;
		}
		return origFiles;
	}
	
	/**
	 * eg: cmread-books\dushi\16
	 * */
	public static String getDifferPath(File subFile, File ancestorFile)
	{
		File parentFile = subFile.getParentFile();
		String dirpath = "";
		while (!parentFile.getPath().equalsIgnoreCase(ancestorFile.getPath()))
		{
			dirpath = String.format("%s\\%s", parentFile.getName(), dirpath);
			parentFile = parentFile.getParentFile();
		}
		return dirpath;
	}
	
	public static void makeDir(String path)
	{
		File dirFile = new File(path);
		if (!dirFile.exists())
		{
			dirFile.mkdirs();
		}	
	}
	
	/**
	 * find file/dir toFindFileName from ancestors of searchDirName
	 * */
	public static File findDecestorFile(File searchDir, String toFindFileName)
	{
		if (searchDir.getName().equalsIgnoreCase(toFindFileName))
		{
			return searchDir;
		}
		if (searchDir.isDirectory())
		{
			File[] subFiles = searchDir.listFiles();
			for (File subFile : subFiles)
			{
				File temp = findDecestorFile(subFile, toFindFileName);
				if (temp != null)
				{
					return temp;
				}
			}
		}
		return null;
	}
	
	public static File findFile(String fileName, File parentFile, int compType)
	{
		File[] files = parentFile.listFiles();
		switch (compType) {
		case 0: //equal
			for (File file : files)
			{
				if (file.getName().equalsIgnoreCase(fileName))
				{
					return file;
				}
			}
			break;
		case 1: //start with
			for (File file : files)
			{
				if (file.getName().toLowerCase().startsWith(fileName.toLowerCase()))
				{
					return file;
				}
			}
			break;
		case 2: //contains
			for (File file : files)
			{
				if (file.getName().toLowerCase().indexOf(fileName.toLowerCase()) != -1)
				{
					return file;
				}
			}
			break;
		default:
			break;
		}
		
		return null;
	}
	private static final char BOM = '\uFEFF';
	public static ArrayList<String> readTxtFile(String fileName,String encoding)  {
		ArrayList<String> rtn = new ArrayList<String>();
		BufferedReader reader = null;
		try {
			reader = new BufferedReader(new InputStreamReader(new FileInputStream(fileName), encoding));
			String line = null;
			boolean isFirstLine = true;
			while ((line = reader.readLine()) != null) {
				if (isFirstLine && line.length() > 0 && line.charAt(0) == BOM) {
					line = line.substring(1);
					isFirstLine = false;
				}
				rtn.add(line);
			}
		} catch (Exception e) {
			String errMsg = String.format("Exception while reading file: %s", fileName, e.getMessage());
			e.printStackTrace();
		} finally {
			if (reader != null) {
				try {
					reader.close();
				} catch (IOException e) {
					String errMsg = String.format("Exception while closing file [%s]: %s", fileName, e.getMessage());
					e.printStackTrace();
				}
			}
		}
		return rtn;
	}

	public static void copyFile(File source, File dest) throws IOException {
		FileChannel inputChannel = null;
		FileChannel outputChannel = null;
		try {
			inputChannel = new FileInputStream(source).getChannel();
			outputChannel = new FileOutputStream(dest).getChannel();
			outputChannel.transferFrom(inputChannel, 0, inputChannel.size());
		} finally {
			inputChannel.close();
			outputChannel.close();
		}
	}
	
	public static List<String> findFiles(String ph) {
		List<String> filesList = new ArrayList<String>();
		File file = new File(ph);
		if (!file.exists()) {
			return null;
		}
		File tempFile;
		File[] files = file.listFiles();
		for (int i = 0; i < files.length; i++) {
			tempFile = files[i];
			if (tempFile.isFile()) {
				filesList.add(tempFile.getName().toString());
			}
		}
		return filesList;
	}
}
