package de.stoermer.redditdownloader;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URL;
import java.util.Arrays;
import java.util.List;

import com.google.gson.Gson;

import de.stoermer.redditdownloader.domain.Child;
import de.stoermer.redditdownloader.domain.RedditResponse;

public class Downloader {
	private static final String BASE_URL = "https://www.reddit.com/r/";
	private final ImageDownloader id;
	private final String subreddit;

	public Downloader(final String subreddit) {
		this.subreddit = subreddit;
		this.id = new ImageDownloader(subreddit);
	}
	
	public void downloadCurrent() {
		List<String> urls = Arrays.asList(BASE_URL + subreddit + "/.json?limit=100&after=",
				BASE_URL + subreddit + "/best/.json?limit=100&after=",
				BASE_URL + subreddit + "/hot/.json?limit=100&after=",
				BASE_URL + subreddit + "/new/.json?limit=100&after=",
				BASE_URL + subreddit + "/top/.json?limit=100&after=",
				BASE_URL + subreddit + "/top/.json?t=week&limit=100&after=",
				BASE_URL + subreddit + "/top/.json?t=month&limit=100&after=",
				BASE_URL + subreddit + "/top/.json?t=year&limit=100&after=",
				BASE_URL + subreddit + "/top/.json?t=all&limit=100&after=");

		for (String url : urls) {
			System.out.println("*--------------------------------------*");
			System.out.println("Verarbeite URL: " + url);
			System.out.println("*--------------------------------------*");

			doDownload(url);
		}
	}

	private void doDownload(String url) {
		String lastChildName = "XYZ";
		boolean running = true;
		while (running) {

			var startTime = System.currentTimeMillis();
			var json = doGet(url + lastChildName);

			Gson gson = new Gson();
			RedditResponse response = gson.fromJson(json, RedditResponse.class);
			System.out.println("Neues Paket - Children: " + response.getData().getChildren().size());
			for (Child child : response.getData().getChildren()) {
				lastChildName = child.getData().getName();
				if (isImage(child)) {
					
					id.downloadImage(child.getData().getUrl(), child.getData().getAuthor(), getImageName(child));
				}
			}
			if (response.getData().getChildren().size() == 0) {
				running = false;
			} else {
				try {
					long duration = System.currentTimeMillis() - startTime;
					System.out.println("Dauer für Durchlauf: " + duration + "ms");
					if (duration < 6000) {
						Thread.sleep(6000 - duration);
					}
					System.out.println("Letztes Kind: " + lastChildName);
				} catch (InterruptedException e) {
					e.printStackTrace();
					Thread.interrupted();
				}
			}
		}
	}

	private boolean isImage(Child child) {
		String url = child.getData().getUrl().toLowerCase();
		return url.endsWith(".jpeg") || url.endsWith(".png") || url.endsWith(".gif");
	}

	private String getImageName(Child child) {
		var url = child.getData().getUrl();
		return url.substring(url.lastIndexOf("/") + 1);
	}

	private String doGet(String urlAsString) {
		try {
			URL url = new URI(urlAsString).toURL();
			var con = (HttpURLConnection) url.openConnection();
			con.setRequestMethod("GET");
			con.setRequestProperty("User-Agent", "desktop:de.xxx.redditdownloader (by /u/sohn_des_odin)");
			int status = con.getResponseCode();

			if (status == 429) {
				String retryAfter = con.getHeaderField("Retry-After");
				System.err.println("Rate Limit! Warte " + (retryAfter != null ? retryAfter : "60") + " Sekunden.");
				return null; // Oder wirf eine eigene Exception
			}

			if (status >= 400) {
				InputStream errorStream = con.getErrorStream();
				if (errorStream != null) {
					try (var reader = new BufferedReader(new InputStreamReader(errorStream))) {
						StringBuilder errorResponse = new StringBuilder();
						String line;
						while ((line = reader.readLine()) != null) {
							errorResponse.append(line);
						}
						System.err.println("HTTP Fehler " + status + " erhalten!");
						System.err.println("Servermeldung: " + errorResponse.toString());
					}
				}
			}

			var reader = new BufferedReader(new InputStreamReader(con.getInputStream()));
			String inputLine = null;
			var builder = new StringBuilder();
			while ((inputLine = reader.readLine()) != null) {
				builder.append(inputLine);
			}
			return builder.toString();
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
}
