package de.duehl.html.download.data;

import java.util.ArrayList;
import java.util.List;

import de.duehl.basics.text.Text;

/**
 * Diese Klasse stellt das Ergebnis des Downloads dar.
 *
 * Wir kümmern uns um die Redirects selbst, daher sind hier ggf. mehrere Ergebnisse von einzelnen
 * Downloads, die nacheinander durchgeführt werden, in der Liste.
 *
 * @version 1.01     2017-06-21
 * @author Christian Dühl
 */

public class DownloadInfoWithRedirects {

    /** Die Url, die ursprünglich heruntergeladen werden sollte. */
    private final String url;

    /** Liste mit den Ergebnissen eines Downloads, ohne sich um Redirects zu kümmern. */
    private final List<DownloadInfo> infosOfEachHop;

    /** Gibt an, dass zu viele Redirects hintereinander erfolgt sind. */
    private boolean tooMuchRedirects;

    /** Gibt an, ob zyklische Redirects erkannt wurden. */
    private boolean redirectCycleDetected;

    /** Gibt an, ob eine Weiterleitung auf die Navigationshilfe von T-Online entdeckt wurde. */
    private boolean redirectToNavigationshilfeTOnline;

    /** Gibt an, ob der Download wegen Zeitüberschreitung abgebrochen wurde. */
    private boolean downloadCanceled;

    /** Gibt an, ob eine Ausnahme beim Download aufgetreten ist. */
    private boolean excpetionOccured;

    /** Beim Download aufgetretene Ausnahme. */
    private Exception excpetion;

    /**
     * Konstruktor.
     *
     * @param url
     *            Die Url, die ursprünglich heruntergeladen werden sollte.
     */
    public DownloadInfoWithRedirects(String url) {
        this.url = url;
        infosOfEachHop = new ArrayList<>();
        tooMuchRedirects = false;
        redirectCycleDetected = false;
        redirectToNavigationshilfeTOnline = false;
        downloadCanceled = false;
        excpetionOccured = false;
        excpetion = new Exception("Keine Ausnahme aufgetreten! DownloadInfoWithRedirects");
    }

    /** Stellt fest, ob ein DownloadErgebnis schonmal hier aufgetaucht ist. */
    public boolean isHopKnown(DownloadInfo info) {
        String infoUrl = info.getUrl();
        for (DownloadInfo hopInfo : infosOfEachHop) {
            String hopUrl = hopInfo.getUrl();
            if (infoUrl.equals(hopUrl)) {
                return true;
            }
        }

        return false;
    }

    /** Fügt das Ergebnis eines Downloads (ohne sich um Redirects zu kümmern) hinzu. */
    public void addHop(DownloadInfo info) {
        infosOfEachHop.add(info);
    }

    /** Gibt an, dass zu viele Redirects hintereinander erfolgt sind. */
    public void tooMuchRedirects() {
        tooMuchRedirects = true;
    }

    /** Gibt an, ob zyklische Redirects erkannt wurden. */
    public void redirectCycleDetected() {
        redirectCycleDetected = true;
    }

    /** Gibt an, dass eine Weiterleitung auf die Navigationshilfe von T-Online entdeckt wurde. */
    public void redirectToNavigationshilfeTOnline() {
        redirectToNavigationshilfeTOnline = true;
    }

    /** Wird aufgerufen, wenn der Download zu lange dauerte und deshalb beendet wurde. */
    public void downloadCanceled() {
        downloadCanceled = true;
    }

    /** Beim Download ist die angegebene Ausnahme aufgetreten. */
    public void exceptionOccured(Exception excpetion) {
        excpetionOccured = true;
        this.excpetion = excpetion;
    }

    /** Getter für die Url, die ursprünglich heruntergeladen werden sollte. */
    public String getUrl() {
        return url;
    }

    /** Getter für die Liste mit den Ergebnissen eines Downloads, ohne sich um Redirects zu kümmern. */
    public List<DownloadInfo> getInfosOfEachHop() {
        return infosOfEachHop;
    }

    /** Gibt an, dass zu viele Redirects hintereinander erfolgt sind. */
    public boolean hasTooMuchRedirects() {
        return tooMuchRedirects;
    }

    /** Gibt an, ob zyklische Redirects erkannt wurden. */
    public boolean isRedirectCycleDetected() {
        return redirectCycleDetected;
    }

    /** Gibt an, ob eine Weiterleitung auf die Navigationshilfe von T-Online entdeckt wurde. */
    public boolean isRedirectToNavigationshilfeTOnline() {
        return redirectToNavigationshilfeTOnline;
    }

    /** Gibt an, ob der Download wegen Zeitüberschreitung abgebrochen wurde. */
    public boolean isDownloadCanceled() {
        return downloadCanceled;
    }

    /** Gibt an, ob eine Ausnahme beim Download aufgetreten ist. */
    public boolean isExcpetionOccured() {
        return excpetionOccured;
    }

    /** Getter für die beim Download aufgetretene Ausnahme. */
    public Exception getExcpetion() {
        return excpetion;
    }

    /** Getter für die ReturnedUrl des letzten Hops. */
    public String getTargetUrl() {
        int numberOfHops = infosOfEachHop.size();
        if (numberOfHops < 1) {
            return "";
        }
        else {
            DownloadInfo hop = infosOfEachHop.get(numberOfHops - 1);
            return hop.getReturnedUrl();
        }
    }

    /** Gibt an, ob der Download erfolgreich war. */
    public boolean isDownloadSuccessfull() {
        int numberOfHops = infosOfEachHop.size();
        if (redirectCycleDetected
                || tooMuchRedirects
                || redirectToNavigationshilfeTOnline
                || downloadCanceled
                || excpetionOccured
                || numberOfHops < 1) {
            return false;
        }
        else {
            DownloadInfo hop = infosOfEachHop.get(numberOfHops - 1);
            return hop.isDownloadSuccessfull();
        }
    }

    /** Getter für den Inhalt der Ziel-Seite in UTF-8. */
    public String getTargetContent() {
        int numberOfHops = infosOfEachHop.size();
        if (numberOfHops < 1) {
            return "";
        }
        else {
            DownloadInfo hop = infosOfEachHop.get(numberOfHops - 1);
            return hop.getContent();
        }
    }

    @Override
    public String toString() {
        return "DownloadInfoWithRedirects [url=" + url + ", infosOfEachHop=" + infosOfEachHop
                + ", tooMuchRedirects=" + tooMuchRedirects + ", redirectCycleDetected="
                + redirectCycleDetected + ", redirectToNavigationshilfeTOnline="
                + redirectToNavigationshilfeTOnline + ", downloadCanceled=" + downloadCanceled
                + ", excpetionOccured=" + excpetionOccured + ", excpetion=" + excpetion + "]";
    }

    public String toStringWithoutContent() {
        return "DownloadInfoWithRedirects [url=" + url + ", infosOfEachHop="
                + infosOfEachHoptoStringWithoutContent() + ", tooMuchRedirects=" + tooMuchRedirects
                + ", redirectCycleDetected=" + redirectCycleDetected
                + ", redirectToNavigationshilfeTOnline=" + redirectToNavigationshilfeTOnline
                + ", downloadCanceled=" + downloadCanceled + ", excpetionOccured="
                + excpetionOccured + ", excpetion=" + excpetion + "]";
    }

    private String infosOfEachHoptoStringWithoutContent() {
        List<String> toStringWithoutContents = new ArrayList<>();
        for (DownloadInfo info : infosOfEachHop) {
            toStringWithoutContents.add(info.toStringWithoutContent());
        }
        return "[ " + Text.join(", ", toStringWithoutContents) + " ]";
    }

}
