package de.oaa.xxx.games.bdsm.sperre;

import java.time.LocalDateTime;
import java.util.Optional;
import java.util.Random;
import java.util.UUID;

import com.fasterxml.jackson.databind.ObjectMapper;

import de.oaa.xxx.games.common.aufgaben.AufgabenList;
import de.oaa.xxx.games.common.aufgaben.Sperre;
import de.oaa.xxx.games.bdsm.entity.AktiveSperreEntity;
import de.oaa.xxx.games.bdsm.entity.BdsmGameEntity;
import de.oaa.xxx.games.bdsm.entity.MitspielerEntity;
import de.oaa.xxx.games.bdsm.repository.AktiveSperreRepository;
import de.oaa.xxx.games.bdsm.repository.BdsmGameRepository;
import de.oaa.xxx.games.bdsm.repository.MitspielerRepository;

public class SperreVerarbeiten {

    private final ObjectMapper objectMapper = new ObjectMapper();

    public void sperreAnwenden(SperreCallback callback, BdsmGameRepository sessionRepository,
                                MitspielerRepository mitspielerRepository, AktiveSperreRepository sperreRepository) throws Exception {
        BdsmGameEntity session = sessionRepository.findById(callback.getSessionId()).orElse(null);
        MitspielerEntity mitspieler = mitspielerRepository.findById(callback.getSpielerId()).orElse(null);
        if (session != null) {
            AufgabenList aufgaben = objectMapper.readValue(session.getAufgaben(), AufgabenList.class);
            Optional<Sperre> first = aufgaben.getSperren().stream()
                    .filter(sperre -> sperre.getSperreId().equals(callback.getSperreId()))
                    .findFirst();
            if (first.isPresent()) {
                Sperre sperre = first.get();
                AktiveSperreEntity aktiv = new AktiveSperreEntity();
                fill(callback, session, mitspieler, sperre, aktiv);
                sperreRepository.save(aktiv);
                sperre.getSperreFuer().forEach(mitspieler.getWerkzeuge()::remove);
                mitspielerRepository.save(mitspieler);
            }
        }
    }

    public String sperreAufheben(AktiveSperreEntity aufzuheben, AktiveSperreRepository sperreRepository,
                                   MitspielerRepository mitspielerRepository) {
        MitspielerEntity mitspieler = aufzuheben.getMitspieler();
        aufzuheben.getFuer().forEach(mitspieler.getWerkzeuge()::add);
        mitspielerRepository.save(mitspieler);
        String releaseText = aufzuheben.getReleaseText();
        sperreRepository.delete(aufzuheben);
        return releaseText;
    }

    public void sperreVerlaengern(AktiveSperreEntity verlaengern, Integer faktor, AktiveSperreRepository sperreRepository) {
        Integer neueDauer = verlaengern.getMinuten() * faktor;
        verlaengern.setEndzeit(verlaengern.getStartzeit().plusMinutes(neueDauer));
        verlaengern.setMinuten(neueDauer);
        sperreRepository.save(verlaengern);
    }

    private void fill(SperreCallback callback, BdsmGameEntity session, MitspielerEntity mitspieler,
                       Sperre sperre, AktiveSperreEntity aktiv) {
        aktiv.setAktiveSperreId(UUID.randomUUID());
        LocalDateTime now = LocalDateTime.now();
        Integer minuten = berechneDauer(session, sperre);
        aktiv.setStartzeit(now);
        aktiv.setEndzeit(now.plusMinutes(minuten));
        aktiv.setMinuten(minuten);
        aktiv.setMitspieler(mitspieler);
        aktiv.setSession(session);
        aktiv.setFuer(sperre.getSperreFuer());
        aktiv.setReleaseText(callback.getReleaseText());
    }

    private Integer berechneDauer(BdsmGameEntity session, Sperre sperre) {
        Integer minuten = 30;
        if (sperre.getMinutenVon() != null) {
            if (sperre.getMinutenBis() != null) {
                minuten = new Random().nextInt(sperre.getMinutenVon(), sperre.getMinutenBis());
            } else {
                minuten = sperre.getMinutenVon();
            }
        }
        if (session.getZeitfaktorZeitstrafen() != null) {
            minuten = (int) (minuten * session.getZeitfaktorZeitstrafen());
        }
        if (minuten == 0) {
            minuten = 1;
        }
        return minuten;
    }
}
