package com.app.baselibrary.commonUtil;

import android.content.Context;
import android.os.Build;
import android.os.Environment;
import android.os.StatFs;
import android.support.annotation.RequiresApi;
import android.text.format.Formatter;
import android.util.Log;

import com.app.baselibrary.base.app.BaseApplication;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.DecimalFormat;
import java.util.List;

import okhttp3.ResponseBody;

/**
 * Desc: 文件工具类；
 * Author: pl
 * Date: 2017-03-13 18:14
 */

public class FileUtils {

    private static final String TAG = "FileUtils";
    public static final String SD_PATH = Environment.getExternalStorageDirectory() + "/";
    public static final String RES_CACHE_PATH = "/res_cache";

    public static String readAssetsTxt(Context context, String fileName) {
        try {
            InputStream is = context.getAssets().open(fileName);
            int size = is.available();
            byte[] buffer = new byte[size];
            is.read(buffer);
            is.close();
            String text = new String(buffer, "utf-8");
            return text;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "读取错误，请检查文件名";
    }

    public static File getCacheDir(Context context, String dirName) {
        File result;
        if (existsSdcard()) {
            LogUtil.e(TAG, "isExistsSdcard");
            File cacheDir = context.getApplicationContext().getExternalCacheDir();
            if (cacheDir == null) {
                LogUtil.e(TAG, "cacheDir == null");
                result = new File(Environment.getExternalStorageDirectory(),
                        "Android/data/" + context.getApplicationContext().getPackageName() + "/cache/" + dirName);
            } else {
                result = new File(cacheDir, dirName);
            }
        } else {
            LogUtil.e(TAG, "not isExistsSdcard");
            result = new File(context.getApplicationContext().getCacheDir(), dirName);
        }
        if (result.exists() || result.mkdirs()) {
            return result;
        } else {
            return null;
        }
    }

    //内部存储视频根目录
    @RequiresApi(api = Build.VERSION_CODES.N)
    public static File getRooteMoviesFile(Context context, String dirName) {
        File result = null;
        if (existsSdcard()) {
            result = new File(Environment.getExternalStorageDirectory(), "Movies/download/" + dirName);
        } else {
            LogUtil.e(TAG, "not isExistsSdcard");
            result = new File(context.getApplicationContext().getDataDir(), "Movies/download/" + dirName);
        }
        try {
            if (!result.getParentFile().exists()) {
                boolean isMkdirs = result.getParentFile().mkdirs();
                if (!isMkdirs) {
                    return null;
                }
            }
            if (result.exists() || result.createNewFile()) {
                return result;
            } else {
                return null;
            }
        } catch (Exception e) {
            return null;
        }

    }

    //内部存储视频根目录（Movies文件夹）
    @RequiresApi(api = Build.VERSION_CODES.N)
    public static File getRooteMovies(Context context) {
        File result = null;
        if (existsSdcard()) {
            result = new File(Environment.getExternalStorageDirectory(), "Movies/");
        } else {
            LogUtil.e(TAG, "not isExistsSdcard");
            result = new File(context.getApplicationContext().getDataDir(), "Movies/");
        }
        try {
            if (!result.getParentFile().exists()) {
                boolean isMkdirs = result.getParentFile().mkdirs();
                if (!isMkdirs) {
                    return null;
                }
            }
            if (result.exists() || result.createNewFile()) {
                return result;
            } else {
                return null;
            }
        } catch (Exception e) {
            return null;
        }

    }

    public static File getCacheFile(Context context, String dirName) {
        File result;
        if (existsSdcard()) {
            LogUtil.e(TAG, "isExistsSdcard");
            File cacheDir = context.getApplicationContext().getExternalCacheDir();
            if (cacheDir == null) {
                LogUtil.e(TAG, "cacheDir == null");
                result = new File(Environment.getExternalStorageDirectory(),
                        "Android/data/" + context.getApplicationContext().getPackageName() + "/cache/" + dirName);
            } else {
                result = new File(cacheDir, dirName);
            }
        } else {
            LogUtil.e(TAG, "not isExistsSdcard");
            result = new File(context.getApplicationContext().getCacheDir(), dirName);
        }
        try {
            if (!result.getParentFile().exists()) {
                boolean isMkdirs = result.getParentFile().mkdirs();
                if (!isMkdirs) {
                    return null;
                }
            }
            if (result.exists() || result.createNewFile()) {
                return result;
            } else {
                return null;
            }
        } catch (Exception e) {
            return null;
        }

    }

    /**
     * 检查磁盘空间是否大于10mb
     *
     * @return true 大于
     */
    public static boolean isDiskAvailable() {
        long size = getDiskAvailableSize();
        return size > 10 * 1024 * 1024; // > 10bm
    }

    /**
     * 获取磁盘可用空间
     *
     * @return byte 单位 kb
     */
    public static long getDiskAvailableSize() {
        if (!existsSdcard()) return 0;
        File path = Environment.getExternalStorageDirectory(); // 取得sdcard文件路径
        StatFs stat = new StatFs(path.getAbsolutePath());
        long blockSize = stat.getBlockSize();
        long availableBlocks = stat.getAvailableBlocks();
        return availableBlocks * blockSize;
        // (availableBlocks * blockSize)/1024 KIB 单位
        // (availableBlocks * blockSize)/1024 /1024 MIB单位
    }

    public static Boolean existsSdcard() {
        return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
    }

    /**
     * 清楚文件夹中的内容；
     *
     * @param dirPath
     */
    public static void clearFileDirectory(String dirPath) {
        File dir = new File(dirPath);
        if (!dir.exists()) {
            dir.mkdir();
        } else {
            if (dir.isDirectory()) {
                File[] files = dir.listFiles();

                if (files != null && files.length > 0) {
                    for (File f : files) {
                        if (f.isFile())
                            f.delete();
                    }
                }
            }
        }
    }

    public static long getFileOrDirSize(File file) {
        if (!file.exists()) return 0;
        if (!file.isDirectory()) return file.length();

        long length = 0;
        File[] list = file.listFiles();
        if (list != null) { // 文件夹被删除时, 子文件正在被写入, 文件属性异常返回null.
            for (File item : list) {
                length += getFileOrDirSize(item);
            }
        }

        return length;
    }

    public static boolean deleteDownloadInstalledApk(String filePath, String name) {
        LogUtil.e("delet_filePath", filePath + "---" + name);
        File file = new File(filePath + File.separator + name);
        if (file.exists()) {
            LogUtil.e("file_name", file.getAbsolutePath());
            String tmpPath = file.getParent() + File.separator + System.currentTimeMillis();
            File tmp = new File(tmpPath);
            file.renameTo(tmp);
            return tmp.delete();
        }
        return false;
    }

    /**
     * 复制文件到指定文件
     *
     * @param fromPath 源文件
     * @param toPath   复制到的文件
     * @return true 成功，false 失败
     */
    public static boolean copy(String fromPath, String toPath) {
        boolean result = false;
        File from = new File(fromPath);
        if (!from.exists()) {
            return result;
        }

        File toFile = new File(toPath);
        IOUtil.deleteFileOrDir(toFile);
        File toDir = toFile.getParentFile();
        if (toDir.exists() || toDir.mkdirs()) {
            FileInputStream in = null;
            FileOutputStream out = null;
            try {
                in = new FileInputStream(from);
                out = new FileOutputStream(toFile);
                IOUtil.copy(in, out);
                result = true;
            } catch (Throwable ex) {
                LogUtil.d(TAG, ex.getMessage());
                result = false;
            } finally {
                IOUtil.closeQuietly(in);
                IOUtil.closeQuietly(out);
            }
        }
        return result;
    }

    /**
     * 在SD卡上创建文件
     *
     * @param fileName
     * @return
     * @throws IOException
     */
    public static File createSDFile(String fileName) {
        File file = new File(SD_PATH + fileName);
        try {
            file.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return file;
    }

    /**
     * 在SD卡上创建目录
     *
     * @param dirName
     * @return
     */
    public static File createSDDir(String dirName) {
        File dir = new File(SD_PATH + dirName);
        dir.mkdir();
        return dir;
    }

    /**
     * 判断SD卡上的文件夹是否存在
     *
     * @param fileName
     * @return
     */
    public boolean isFileExist(String fileName) {
        File file = new File(SD_PATH + fileName);
        return file != null && file.exists();
    }

    /**
     * 将一个InputStream里面的数据写入到SD卡中
     *
     * @param path
     * @param fileName
     * @param input
     * @return
     */
    public File write2SDFromInput(String path, String fileName, InputStream input) {
        File file = null;
        OutputStream output = null;
        try {
            createSDDir(path);
            file = createSDFile(path + fileName);

            output = new FileOutputStream(file);

            byte[] buffer = new byte[10 * 1024];

            int length;
            while ((length = (input.read(buffer))) > 0) {
                output.write(buffer, 0, length);
            }
            output.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (output != null) {
                    output.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return file;
    }

    public static void deleteFile(String fileSavePath) {
        File file = new File(fileSavePath);
        if (file.exists()) {
            file.delete();
        } else {
            //当资源还没有下完成的时候,删除临时文件;
            file = new File(fileSavePath + ".tmp");
            if (file.exists()) {
                file.delete();
            }
        }
    }


    /**
     * 拿到临时文件的存储路径；
     *
     * @return
     */
    public static String getCacheDir(Context context) {

        File file = context.getExternalFilesDir(RES_CACHE_PATH);
        if (!file.exists()) {
            file.mkdir();
        }
        return file.getAbsolutePath();
    }

    /**
     * 删除文件；
     *
     * @param filePath
     */
    public static void delFile(String filePath) {
        File file = new File(filePath);
        if (file.exists())
            file.delete();

        File file1 = new File(filePath + ".tmp");
        if (file1.exists())
            file1.delete();

    }

    public static boolean writeToFile(ResponseBody body, File file) {
        try {
            InputStream inputStream = null;
            OutputStream outputStream = null;
            try {
                byte[] fileReader = new byte[2048];
                inputStream = body.byteStream();
                outputStream = new FileOutputStream(file);
                while (true) {
                    int read = inputStream.read(fileReader);
                    if (read == -1) break;
                    outputStream.write(fileReader, 0, read);
                }
                outputStream.flush();
                return true;
            } catch (IOException e) {
                return false;
            } finally {
                if (inputStream != null) {
                    inputStream.close();
                }
                if (outputStream != null) {
                    outputStream.close();
                }
            }
        } catch (IOException e) {
            return false;
        }
    }

    /**
     * 获取sd卡的指定目录地址；
     *
     * @param context
     * @param dirName
     * @return
     */
    public static File getSdDir(Context context, String dirName) {
        File result;
        if (existsSdcard()) {

            result = new File(Environment.getExternalStorageDirectory(), dirName);

        } else {
            result = new File(context.getApplicationContext().getCacheDir(), dirName);
        }
        if (result.exists() || result.mkdirs()) {
            return result;
        } else {
            return null;
        }
    }

    public static void isCreateFireDir(String downloadPath) {
        File dir = new File(downloadPath);
        if (!dir.exists()) {
            dir.mkdirs();
        }
    }

    //删除文件夹和文件夹里面的文件
    public static void deleteDirWihtFile(File dir) {
        if (dir == null || !dir.exists() || !dir.isDirectory())
            return;
        for (File file : dir.listFiles()) {
            if (file.isFile())
                file.delete(); // 删除所有文件
            else if (file.isDirectory())
                deleteDirWihtFile(file); // 递规的方式删除文件夹
        }
        dir.delete();// 删除目录本身
    }

    /**
     * 获取文件夹下所有文件
     *
     * @param dir
     * @param fileList
     */
    public static void getDirListFiles(File dir, List<File> fileList) {
        if (dir == null || !dir.exists() || !dir.isDirectory())
            return;
        for (File file : dir.listFiles()) {
            if (file.isFile()) {
                fileList.add(file);
            } else if (file.isDirectory()) {
                getDirListFiles(file, fileList);
            }
        }
    }

    public static String getSDPath() {
        File sdDir = null;
        boolean sdCardExist = Environment.getExternalStorageState()
                .equals(Environment.MEDIA_MOUNTED); //判断sd卡是否存在
        if (sdCardExist) {
            sdDir = Environment.getExternalStorageDirectory();//获取跟目录
//            sdDir1 = Environment.getDataDirectory();
//            sdDir2 = Environment.getRootDirectory();
        } else {
            Log.d(TAG, "getSDPath: sd卡不存在");
        }
        Log.d(TAG, "getSDPath: " + sdDir.getAbsolutePath());
        return sdDir.getAbsolutePath();
    }

    /**
     * 调用此方法自动计算指定文件或指定文件夹的大小
     *
     * @param filePath 文件路径
     * @return 计算好的带B、KB、MB、GB的字符串
     */
    public static long getAutoFileOrFilesSize(String filePath) {
        File file = new File(filePath);
        long blockSize = 0;
        try {
            if (file.isDirectory()) {
                blockSize = getFileSizes(file);
            } else {
                blockSize = getFileSize(file);
            }
        } catch (Exception e) {
            e.printStackTrace();
            Log.e(TAG, "获取文件大小失败!");
        }
        return blockSize;
    }

    /**
     * 调用此方法自动计算指定文件或指定文件夹的大小
     *
     * @param filePath 文件路径
     * @return 计算好的带B、KB、MB、GB的字符串
     */
    public static String getAutoFileOrFilesSizeString(String filePath) {
        File file = new File(filePath);
        long blockSize = 0;
        try {
            if (file.isDirectory()) {
                blockSize = getFileSizes(file);
            } else {
                blockSize = getFileSize(file);
            }
        } catch (Exception e) {
            e.printStackTrace();
            Log.e(TAG, "获取文件大小失败!");
        }
        return FormetFileSize(blockSize);
    }

    /**
     * 获取指定文件大小
     *
     * @param file
     * @return
     * @throws Exception
     */
    private static long getFileSize(File file) throws Exception {
        long size = 0;
        if (file.exists()) {
            FileInputStream fis = null;
            fis = new FileInputStream(file);
            size = fis.available();
        } else {
            file.createNewFile();
            Log.e(TAG, "获取文件大小不存在!");
        }
        return size;
    }

    /**
     * 转换文件大小
     *
     * @param fileS
     * @return
     */
    public static String FormetFileSize(long fileS) {
        DecimalFormat df = new DecimalFormat("#.00");
        String fileSizeString = "";
        String wrongSize = "0B";
        if (fileS == 0) {
            return wrongSize;
        }
        if (fileS < 1024) {
            fileSizeString = df.format((double) fileS) + "B";
        } else if (fileS < 1048576) {
            fileSizeString = df.format((double) fileS / 1024) + "KB";
        } else if (fileS < 1073741824) {
            fileSizeString = df.format((double) fileS / 1048576) + "MB";
        } else {
            fileSizeString = df.format((double) fileS / 1073741824) + "GB";
        }
        return fileSizeString;
    }

    /**
     * 获取指定文件夹
     *
     * @param f
     * @return
     * @throws Exception
     */
    private static long getFileSizes(File f) throws Exception {
        long size = 0;
        File flist[] = f.listFiles();
        for (int i = 0; i < flist.length; i++) {
            if (flist[i].isDirectory()) {
                size = size + getFileSizes(flist[i]);
            } else {
                size = size + getFileSize(flist[i]);
            }
        }
        return size;
    }

    public static String[] phoneMemory() {
        // 获取存储空间
        File dataFileDir = Environment.getDataDirectory();
        String data = getMemoryInfo(dataFileDir);
        String[] size = data.split("##");
//        tv_totalSize.setText("内部存储总大小：" + d[0]);
//        tv_availabelSize.setText("内部存储可用空间是:" + d[1]);
        return size;
    }

    private static String getMemoryInfo(File path) {
        long blockSize;
        long totalBlockCount;
        long avaiLabelCount;
        // TODO Auto-generated method stub
        StatFs stat = new StatFs(path.getPath());
        //检测系统版本
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
            //获取每个扇区的大小
            blockSize = stat.getBlockSizeLong();
            //获取总共有多少扇区
            totalBlockCount = stat.getBlockCountLong();
            //获取可用扇区数量
            avaiLabelCount = stat.getAvailableBlocksLong();
        } else {
            blockSize = stat.getBlockSize();
            totalBlockCount = stat.getBlockCount();
            avaiLabelCount = stat.getAvailableBlocks();
        }
        // 磁盘总大小
        String totalMemory = Formatter.formatFileSize(BaseApplication.getAppContext(), blockSize * totalBlockCount);
        // 可用大小
        String availabelMemory = Formatter.formatFileSize(BaseApplication.getAppContext(), blockSize * avaiLabelCount);
        //已经用
        String remainingMemory = Formatter.formatFileSize(BaseApplication.getAppContext(), blockSize * (totalBlockCount - avaiLabelCount));
        return totalMemory + "##" + remainingMemory;
    }
}
