package ru.yandex.webmaster3.storage.antispam.threats.data;

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

import com.fasterxml.jackson.annotation.JsonCreator;
import org.joda.time.DateTime;
import org.joda.time.Duration;

import ru.yandex.webmaster3.core.data.WebmasterHostId;
import ru.yandex.webmaster3.core.util.IdUtils;
import ru.yandex.webmaster3.proto.Antispam;

/**
 * @author avhaliullin
 */
public class HostThreatInfo {
    private final String threat;
    private final String sanction;
    private final String displayName;
    private final DateTime lastRecheck;
    private final DateTime nextRecheck;
    private final Duration recheckInterval;
    private final WebmasterHostId threatSourceHost;
    private final boolean allowedToRecheck;
    private final ThreatButtonLockMode lockMode;
    private final DateTime threatConfirmationDate;
    private final List<HostVerdictInfo> verdicts;
    private final ThreatPropagationMode propagationMode;

    @JsonCreator
    public HostThreatInfo(String threat, String sanction, String displayName, DateTime lastRecheck, DateTime nextRecheck,
                          Duration recheckInterval, WebmasterHostId threatSourceHost, boolean allowedToRecheck,
                          ThreatButtonLockMode lockMode, DateTime threatConfirmationDate,
                          List<HostVerdictInfo> verdicts, ThreatPropagationMode propagationMode) {
        this.threat = threat;
        this.sanction = sanction;
        this.displayName = displayName;
        this.lastRecheck = lastRecheck;
        this.nextRecheck = nextRecheck;
        this.recheckInterval = recheckInterval;
        this.threatSourceHost = threatSourceHost;
        this.allowedToRecheck = allowedToRecheck;
        this.lockMode = lockMode;
        this.threatConfirmationDate = threatConfirmationDate;
        this.verdicts = verdicts;
        this.propagationMode = propagationMode;
    }

    public String getThreat() {
        return threat;
    }

    public String getSanction() {
        return sanction;
    }

    public String getDisplayName() {
        return displayName;
    }

    public DateTime getLastRecheck() {
        return lastRecheck;
    }

    public DateTime getNextRecheck() {
        return nextRecheck;
    }

    public Duration getRecheckInterval() {
        return recheckInterval;
    }

    public WebmasterHostId getThreatSourceHost() {
        return threatSourceHost;
    }

    public DateTime getThreatConfirmationDate() {
        return threatConfirmationDate;
    }

    public List<HostVerdictInfo> getVerdicts() {
        return verdicts;
    }

    public boolean isAllowedToRecheck() {
        return allowedToRecheck;
    }

    public HostThreatInfo withAllowedToRecheck(boolean allowedToRecheck) {
        return new HostThreatInfo(threat, sanction, displayName, lastRecheck, nextRecheck, recheckInterval, threatSourceHost,
                allowedToRecheck, lockMode, threatConfirmationDate, verdicts, propagationMode);
    }

    public ThreatButtonLockMode getLockMode() {
        return lockMode;
    }

    public ThreatPropagationMode getPropagationMode() {
        return propagationMode;
    }

    public static HostThreatInfo fromProto(Antispam.ThreatInfo rawThreat) {
        ThreatButtonLockMode lockMode;
        switch (rawThreat.getLockMode()) {
            case TIMED:
                lockMode = ThreatButtonLockMode.TIMED;
                break;
            case UNTIL_UPDATE:
                lockMode = ThreatButtonLockMode.UNTIL_UPDATE;
                break;
            default:
                throw new IllegalArgumentException("Unknown lock mode " + rawThreat.getLockMode());
        }
        List<HostVerdictInfo> verdicts = new ArrayList<>();
        for (Antispam.VerdictInfo rawVerdict : rawThreat.getVerdictsList()) {
            List<VerdictUrlSample> urlSamples = new ArrayList<>();
            for (Antispam.UrlSample rawSample : rawVerdict.getSamplesList()) {
                urlSamples.add(new VerdictUrlSample(
                        rawSample.getUrl(),
                        timeSeconds(rawSample.getUpdateTimestamp()),
                        rawSample.getInfectionChainList()
                ));
            }
            verdicts.add(new HostVerdictInfo(
                    rawVerdict.getVerdict(),
                    urlSamples
            ));
        }
        return new HostThreatInfo(
                rawThreat.getThreat(),
                rawThreat.getSanction(),
                rawThreat.getDisplayName(), rawThreat.hasLastRecheck() ? timeSeconds(rawThreat.getLastRecheck()) : null,
                rawThreat.hasNextRecheck() ? timeSeconds(rawThreat.getNextRecheck()) : null,
                rawThreat.hasRecheckIntervalS() ? Duration.standardSeconds(rawThreat.getRecheckIntervalS()) : null,
                IdUtils.urlToHostId(rawThreat.getThreatSourceHost()),
                rawThreat.getAllowedToRecheck(),
                lockMode,
                rawThreat.hasConfirmationDate() ? timeSeconds(rawThreat.getConfirmationDate()) : null,
                verdicts,
                ThreatPropagationMode.fromProto(rawThreat.getPropagationMode()));
    }

    private static DateTime timeSeconds(long seconds) {
        return seconds == 0L ? null : new DateTime(seconds * 1000);
    }
}
