package com.nincraft.modpackdownloader.util;

import com.nincraft.modpackdownloader.container.DownloadableFile;
import com.nincraft.modpackdownloader.status.DownloadStatus;
import com.nincraft.modpackdownloader.summary.DownloadSummarizer;
import lombok.Getter;
import lombok.extern.log4j.Log4j2;
import lombok.val;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.BooleanUtils;

import java.io.IOException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.Observable;

@Log4j2
public class DownloadHelper extends Observable {

	@Getter
	private DownloadSummarizer downloadSummarizer = new DownloadSummarizer();
	private Arguments arguments;

	public DownloadHelper(Arguments arguments) {
		this.addObserver(downloadSummarizer);
		this.arguments = arguments;
	}

	/**
	 * Downloads a {@link DownloadableFile} moves it to the correct folder. Downloads to the local cache and then
	 * copies to the download folder.
	 *
	 * @param downloadableFile a DownloadableFile with a download URL
	 * @return status of the download, failed, skipped, or success
	 */
	public DownloadStatus downloadFile(final DownloadableFile downloadableFile) {
		return downloadFile(downloadableFile, true);
	}

	/**
	 * Downloads a {@link DownloadableFile} moves it to the correct folder. Downloads to the local cache if
	 * downloadToLocalRepo is set to true and then copies to the download folder.
	 *
	 * @param downloadableFile    a DownloadableFile with a download URL
	 * @param downloadToLocalRepo set to true to keep a copy of the DownloadableFile in local cache
	 * @return status of the download, failed, skipped, or success
	 */
	public DownloadStatus downloadFile(final DownloadableFile downloadableFile, boolean downloadToLocalRepo) {
		DownloadStatus status = DownloadStatus.FAILURE;
		if (BooleanUtils.isTrue(downloadableFile.getSkipDownload())) {
			log.debug("Skipped downloading {}", downloadableFile.getName());
			return notifyStatus(DownloadStatus.SKIPPED);
		}
		String decodedFileName;

		try {
			decodedFileName = URLDecoder.decode(downloadableFile.getFileName(), "UTF-8");
		} catch (final IOException e) {
			log.error("Error Decoding Filename: {}", downloadableFile.getFileName(), e);
			return notifyStatus(DownloadStatus.FAILURE);
		}

		if (FileSystemHelper.getDownloadedFile(decodedFileName, downloadableFile.getFolder()).exists() && !arguments.isForceDownload()) {
			log.debug("Found {} already downloaded, skipping", decodedFileName);
			return notifyStatus(DownloadStatus.SKIPPED);
		}

		if (!FileSystemHelper.isInLocalRepo(downloadableFile.getName(), decodedFileName) || arguments.isForceDownload()) {
			val downloadedFile = FileSystemHelper.getLocalFile(downloadableFile);
			try {
				FileUtils.copyURLToFile(new URL(downloadableFile.getDownloadUrl()), downloadedFile);
			} catch (final IOException e) {
				log.error("Could not download {}.", downloadableFile.getFileName(), e);
				Reference.downloadCount++;
				if ("forge".equals(downloadableFile.getName())) {
					return status;
				}
				return notifyStatus(status);
			}
			status = DownloadStatus.SUCCESS_DOWNLOAD;
		} else {
			status = DownloadStatus.SUCCESS_CACHE;
		}
		FileSystemHelper.moveFromLocalRepo(downloadableFile, decodedFileName, downloadToLocalRepo, arguments.getModFolder());
		log.info("Successfully {} {}", status, downloadableFile.getFileName());
		return notifyStatus(status);
	}

	private DownloadStatus notifyStatus(DownloadStatus status) {
		setChanged();
		notifyObservers(status);
		return status;
	}
}

@@ -448,36 +448,8 @@
 RL;%0A
-import java.net.URLDecoder;%0A
 impo
@@ -1964,201 +1964,33 @@
 %09%09%7D%0A
-%09%09String decodedFileName;%0A%0A%09%09try %7B%0A%09%09%09decodedFileName = URLDecoder.decode(downloadableFile.getFileName(), %22UTF-8%22);%0A%09%09%7D catch (final IOException e) %7B%0A%09%09%09log.error(%22Error Decod
+        Str
 ing 
-Filename: %7B%7D%22,
+fileName =
  dow
@@ -2020,65 +2020,9 @@
 me()
-, e);%0A%09%09%09return notifyStatus(DownloadStatus.FAILURE);%0A%09%09%7D
+;
 %0A%0A%09%09
@@ -2060,24 +2060,17 @@
 dedFile(
-decodedF
+f
 ileName,
@@ -2198,24 +2198,17 @@
 pping%22, 
-decodedF
+f
 ileName)
@@ -2328,24 +2328,17 @@
 Name(), 
-decodedF
+f
 ileName)
@@ -2622,38 +2622,16 @@
 .%22, 
-downloadableFile.getF
+f
 ileName
-()
 , e)
@@ -2942,16 +2942,9 @@
 le, 
-decodedF
+f
 ileN
@@ -3041,38 +3041,16 @@
 us, 
-downloadableFile.getF
+f
 ileName
-()
 );%0A%09

Use given filename when downloading or fetching from cache