/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.filesystem.cts;

import android.content.Context;
import android.util.Log;

import com.android.compatibility.common.util.DeviceReportLog;
import com.android.compatibility.common.util.MeasureRun;
import com.android.compatibility.common.util.MeasureTime;
import com.android.compatibility.common.util.ReportLog;
import com.android.compatibility.common.util.ResultType;
import com.android.compatibility.common.util.ResultUnit;
import com.android.compatibility.common.util.Stat;
import com.android.compatibility.common.util.SystemUtil;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.RandomAccessFile;
import java.util.Random;

public class FileUtil {
    private static final String TAG = "FileUtil";
    private static final Random mRandom = new Random(0);
    private static long mFileId = 0;

    public static final int BUFFER_SIZE = 10 * 1024 * 1024;
    /**
     * create array with different data per each call
     *
     * @param length
     * @param randomSeed
     * @return
     */
    public static byte[] generateRandomData(int length) {
        byte[] buffer = new byte[length];
        int val = mRandom.nextInt();
        for (int i = 0; i < length / 4; i++) {
            // in little-endian
            buffer[i * 4] = (byte)(val & 0x000000ff);
            buffer[i * 4 + 1] = (byte)((val & 0x0000ff00) >> 8);
            buffer[i * 4 + 2] = (byte)((val & 0x00ff0000) >> 16);
            buffer[i * 4 + 3] = (byte)((val & 0xff000000) >> 24);
            val++;
        }
        for (int i = (length / 4) * 4; i < length; i++) {
            buffer[i] = 0;
        }
        return buffer;
    }

    /**
     * create a new file under the given dirName.
     * Existing files will not be affected.
     * @param context
     * @param dirName
     * @return
     */
    public static File createNewFile(Context context, String dirName) {
        File topDir = new File(context.getFilesDir(), dirName);
        topDir.mkdir();
        String[] list = topDir.list();

        String newFileName;
        while (true) {
            newFileName = Long.toString(mFileId);
            boolean fileExist = false;
            for (String child : list) {
                if (child.equals(newFileName)) {
                    fileExist = true;
                    break;
                }
            }
            if (!fileExist) {
                break;
            }
            mFileId++;
        }
        mFileId++;
        //Log.i(TAG, "filename" + Long.toString(mFileId));
        return new File(topDir, newFileName);
    }

    /**
     * create multiple new files
     * @param context
     * @param dirName
     * @param count number of files to create
     * @return
     */
    public static File[] createNewFiles(Context context, String dirName, int count) {
        File[] files = new File[count];
        for (int i = 0; i < count; i++) {
            files[i] = createNewFile(context, dirName);
        }
        return files;
    }

    /**
     * write file with given byte array
     * @param file
     * @param data
     * @param append will append if set true. Otherwise, write from beginning
     * @throws IOException
     */
    public static void writeFile(File file, byte[] data, boolean append) throws IOException {
        final RandomAccessFile randomFile = new RandomAccessFile(file, "rwd"); // force O_SYNC
        if (append) {
            randomFile.seek(randomFile.length());
        } else {
            randomFile.seek(0L);
        }
        randomFile.write(data);
        randomFile.close();
    }

    /**
     * create a new file with given length.
     * @param context
     * @param dirName
     * @param length
     * @return
     * @throws IOException
     */
    public static File createNewFilledFile(Context context, String dirName, long length)
            throws IOException {
        File file = createNewFile(context, dirName);
        final RandomAccessFile randomFile = new RandomAccessFile(file, "rwd"); // force O_SYNC
        byte[] data = generateRandomData(BUFFER_SIZE);

        while (file.length() < length) {
            int toWrite = (int) Math.min(BUFFER_SIZE, length - file.length());
            randomFile.write(data, 0, toWrite);
        }

        randomFile.close();
        return file;
    }

    /**
     * remove given file or directory under the current app's files dir.
     * @param context
     * @param name
     */
    public static void removeFileOrDir(Context context, String name) {
        File entry = new File(context.getFilesDir(), name);
        if (entry.exists()) {
            removeEntry(entry);
        }
    }

    private static void removeEntry(File entry) {
        if (entry.isDirectory()) {
            String[] children = entry.list();
            for (String child : children) {
                removeEntry(new File(entry, child));
            }
        }
        Log.i(TAG, "delete file " + entry.getAbsolutePath());
        entry.delete();
    }

    /**
     * measure time taken for each IO run with amount R/W
     * @param count
     * @param run
     * @param readAmount returns amount of read in bytes for each interval.
     *        Value will not be written if /proc/self/io does not exist.
     * @param writeAmount returns amount of write in bytes for each interval.
     * @return time per each interval
     * @throws IOException
     */
    public static double[] measureIO(int count, double[] readAmount, double[] writeAmount,
            MeasureRun run)  throws Exception {
        double[] result = new double[count];
        File procIo = new File("/proc/self/io");
        boolean measureIo = procIo.exists() && procIo.canRead();
        long prev = System.currentTimeMillis();
        RWAmount prevAmount = new RWAmount();
        if (measureIo) {
            prevAmount = getRWAmount(procIo);
        }
        for (int i = 0; i < count; i++) {
            run.run(i);
            long current =  System.currentTimeMillis();
            result[i] = current - prev;
            prev = current;
            if (measureIo) {
                RWAmount currentAmount = getRWAmount(procIo);
                readAmount[i] = currentAmount.mRd - prevAmount.mRd;
                writeAmount[i] = currentAmount.mWr - prevAmount.mWr;
                prevAmount = currentAmount;
            }
        }
        return result;
    }

    private static class RWAmount {
        public double mRd = 0.0;
        public double mWr = 0.0;
    };

    private static RWAmount getRWAmount(File file) throws IOException {
        RWAmount amount = new RWAmount();

        BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
        String line;
        while((line = br.readLine())!= null) {
            if (line.startsWith("read_bytes")) {
                amount.mRd = Double.parseDouble(line.split(" ")[1]);
            } else if (line.startsWith("write_bytes")) {
                amount.mWr = Double.parseDouble(line.split(" ")[1]);
            }
        }
        br.close();
        return amount;
    }

    /**
     * get file size exceeding total memory size ( 2x total memory).
     * The size is rounded in bufferSize. And the size will be bigger than 400MB.
     * @param context
     * @param bufferSize
     * @return file size or 0 if there is not enough space.
     */
    public static long getFileSizeExceedingMemory(Context context, int bufferSize) {
        long freeDisk = SystemUtil.getFreeDiskSize(context);
        long memSize = SystemUtil.getTotalMemory(context);
        long diskSizeTarget = (2 * memSize / bufferSize) * bufferSize;
        final long minimumDiskSize = (512L * 1024L * 1024L / bufferSize) * bufferSize;
        final long reservedDiskSize = (50L * 1024L * 1024L / bufferSize) * bufferSize;
        if ( diskSizeTarget < minimumDiskSize ) {
            diskSizeTarget = minimumDiskSize;
        }
        if (diskSizeTarget > freeDisk) {
            Log.i(TAG, "Free disk size " + freeDisk + " too small");
            return 0;
        }
        if ((freeDisk - diskSizeTarget) < reservedDiskSize) {
            diskSizeTarget -= reservedDiskSize;
        }
        return diskSizeTarget;
    }

    /**
     *
     * @param context
     * @param dirName
     * @param report
     * @param fileSize
     * @param bufferSize should be power of two
     * @return write throughput in MBPS
     * @throws IOException
     */
    public static double doRandomReadTest(Context context, String dirName, ReportLog report,
            long fileSize, int bufferSize) throws Exception {
        File file = FileUtil.createNewFilledFile(context,
                dirName, fileSize);

        final byte[] data = FileUtil.generateRandomData(bufferSize);
        Random random = new Random(0);
        final int totalReadCount = (int)(fileSize / bufferSize);
        final int[] readOffsets = new int[totalReadCount];
        for (int i = 0; i < totalReadCount; i++) {
            // align in buffer size
            readOffsets[i] = (int)(random.nextFloat() * (fileSize - bufferSize)) &
                    ~(bufferSize - 1);
        }
        final int runsInOneGo = 16;
        final int readsInOneMeasure = totalReadCount / runsInOneGo;

        final RandomAccessFile randomFile = new RandomAccessFile(file, "rw"); // do not need O_SYNC
        double[] rdAmount = new double[runsInOneGo];
        double[] wrAmount = new double[runsInOneGo];
        double[] times = FileUtil.measureIO(runsInOneGo, rdAmount, wrAmount, new MeasureRun() {

            @Override
            public void run(int i) throws IOException {
                Log.i(TAG, "starting " + i + " -th round");
                int start = i * readsInOneMeasure;
                int end = (i + 1) * readsInOneMeasure;
                for (int j = start; j < end; j++) {
                    randomFile.seek(readOffsets[j]);
                    randomFile.read(data);
                }
            }
        });
        randomFile.close();
        double[] mbps = Stat.calcRatePerSecArray((double)fileSize / runsInOneGo / 1024 / 1024,
                times);
        report.addValues("read_throughput", mbps, ResultType.HIGHER_BETTER, ResultUnit.MBPS);
        // This is just the amount of IO returned from kernel. So this is performance neutral.
        report.addValues("read_amount", rdAmount, ResultType.NEUTRAL, ResultUnit.BYTE);
        Stat.StatResult stat = Stat.getStat(mbps);

        report.setSummary("read_throughput_average", stat.mAverage, ResultType.HIGHER_BETTER,
                ResultUnit.MBPS);
        Log.v(TAG, "random read " + stat.mAverage + " MBPS");
        return stat.mAverage;
    }

    /**
     *
     * @param context
     * @param dirName
     * @param report
     * @param fileSize
     * @param bufferSize should be power of two
     * @return write throughput in MBPS
     * @throws IOException
     */
    public static double doRandomWriteTest(Context context, String dirName, ReportLog report,
            long fileSize, int bufferSize) throws Exception {
        File file = FileUtil.createNewFilledFile(context,
                dirName, fileSize);
        final byte[] data = FileUtil.generateRandomData(bufferSize);
        Random random = new Random(0);
        final int totalWriteCount = (int)(fileSize / bufferSize);
        final int[] writeOffsets = new int[totalWriteCount];
        for (int i = 0; i < totalWriteCount; i++) {
            writeOffsets[i] = (int)(random.nextFloat() * (fileSize - bufferSize)) &
                    ~(bufferSize - 1);
        }
        final int runsInOneGo = 16;
        final int writesInOneMeasure = totalWriteCount / runsInOneGo;

        final RandomAccessFile randomFile = new RandomAccessFile(file, "rwd"); // force O_SYNC
        double[] rdAmount = new double[runsInOneGo];
        double[] wrAmount = new double[runsInOneGo];
        double[] times = FileUtil.measureIO(runsInOneGo, rdAmount, wrAmount, new MeasureRun() {

            @Override
            public void run(int i) throws IOException {
                Log.i(TAG, "starting " + i + " -th round");
                int start = i * writesInOneMeasure;
                int end = (i + 1) * writesInOneMeasure;
                for (int j = start; j < end; j++) {
                    randomFile.seek(writeOffsets[j]);
                    randomFile.write(data);
                }
            }
        });
        randomFile.close();
        double[] mbps = Stat.calcRatePerSecArray((double)fileSize / runsInOneGo / 1024 / 1024,
                times);
        report.addValues("write_throughput", mbps, ResultType.HIGHER_BETTER, ResultUnit.MBPS);
        report.addValues("write_amount", wrAmount, ResultType.NEUTRAL, ResultUnit.BYTE);
        Stat.StatResult stat = Stat.getStat(mbps);

        report.setSummary("write_throughput_average", stat.mAverage, ResultType.HIGHER_BETTER,
                ResultUnit.MBPS);
        Log.v(TAG, "random write " + stat.mAverage + " MBPS");
        return stat.mAverage;
    }

    /**
     *
     * @param context
     * @param dirName
     * @param report
     * @param fileSize fileSize should be multiple of bufferSize.
     * @param bufferSize
     * @param numberRepetition
     * @throws IOException
     */
    public static void doSequentialUpdateTest(Context context, String dirName, long fileSize,
            int bufferSize, int numberRepetition, String reportName, String streamName)
            throws Exception {
        File file = FileUtil.createNewFilledFile(context,
                dirName, fileSize);
        final byte[] data = FileUtil.generateRandomData(bufferSize);
        int numberRepeatInOneRun = (int)(fileSize / bufferSize);
        double[] mbpsAll = new double[numberRepetition * numberRepeatInOneRun];
        for (int i = 0; i < numberRepetition; i++) {
            Log.i(TAG, "starting " + i + " -th round");
            DeviceReportLog report = new DeviceReportLog(reportName, streamName);
            report.addValue("round", i,  ResultType.NEUTRAL, ResultUnit.NONE);
            final RandomAccessFile randomFile = new RandomAccessFile(file, "rwd");  // force O_SYNC
            randomFile.seek(0L);
            double[] times = MeasureTime.measure(numberRepeatInOneRun, new MeasureRun() {

                @Override
                public void run(int i) throws IOException {
                    randomFile.write(data);
                }
            });
            randomFile.close();
            double[] mbps = Stat.calcRatePerSecArray((double)bufferSize / 1024 / 1024,
                    times);
            report.addValues("throughput", mbps, ResultType.HIGHER_BETTER, ResultUnit.MBPS);
            int offset = i * numberRepeatInOneRun;
            for (int j = 0; j < mbps.length; j++) {
                mbpsAll[offset + j] = mbps[j];
            }
            report.submit();
        }
        Stat.StatResult stat = Stat.getStat(mbpsAll);
        DeviceReportLog report = new DeviceReportLog(reportName, String.format("%s_average",
                streamName));
        report.addValue("update_throughput", stat.mAverage, ResultType.HIGHER_BETTER,
                ResultUnit.MBPS);
        report.submit();
    }
}
