package com.atlassian.bitbucket.util;

import com.google.common.io.ByteStreams;

import java.io.*;

/**
 * Utilities for I/O operations.
 */
public class IoUtils {

    /**
     * Copies the contents of one file to another. If the destination file already exists, it is <i>overwritten</i>.
     * To append to the destination file, use {@link #copy(File, OutputStream)} and create a {@code FileOutputStream}
     * in append mode.
     *
     * @param in  the source file to read from
     * @param out the destination file to write to, which is created if it doesn't exist and <i>overwritten</i> if
     *            it does exist
     * @return the number of bytes copied
     * @throws IOException if copying fails
     */
    public static long copy(File in, File out) throws IOException {
        try (OutputStream outputStream = new FileOutputStream(out)) {
            return copy(in, outputStream);
        }
    }

    /**
     * Copies the contents of the specified file to the provided {@code OutputStream}.
     * <p>
     * <b>Warning</b>: The {@code OutputStream} <i>belongs to the caller</i>. This method will <i>not</i> close it;
     * it is left to the caller to manage the stream's lifecycle.
     *
     * @param in           the source file to read from
     * @param outputStream the stream to write to, <i>which will not be closed</i>
     * @return the number of bytes copied
     * @throws IOException if copying fails
     */
    public static long copy(File in, OutputStream outputStream) throws IOException {
        try (InputStream inputStream = new FileInputStream(in)) {
            return ByteStreams.copy(inputStream, outputStream);
        }
    }

    /**
     * Reads from the provided {@code InputStream} and writes its contents to the specified file.
     * <p>
     * <b>Warning</b>: The {@code InputStream} <i>belongs to the caller</i>. This method will <i>not</i> close it;
     * it is left to the caller to manage the stream's lifecycle.
     *
     * @param inputStream the stream to read from, <i>which will not be closed</i>
     * @param out         the destination file to write to, which is created if it doesn't exist and <i>overwritten</i>
     *                    if it does exist
     * @return the number of bytes copied
     * @throws IOException if copying fails
     */
    public static long copy(InputStream inputStream, File out) throws IOException {
        try (FileOutputStream outputStream = new FileOutputStream(out)) {
            return ByteStreams.copy(inputStream, outputStream);
        }
    }
}
