package de.accso.flexinale.backoffice.infrastructure.persistence.mapper;

import de.accso.flexinale.backoffice.domain.model.Kino;
import de.accso.flexinale.backoffice.domain.model.KinoSaal;
import de.accso.flexinale.backoffice.infrastructure.persistence.KinoEntity;
import de.accso.flexinale.backoffice.infrastructure.persistence.KinoSaalEntity;

import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

import static de.accso.flexinale.common.shared_kernel.RawWrapper.getRawOrNull;

public final class KinoKinoSaalEntity2KinoKinoSaalMapper {

    public static Kino mapKino(final KinoEntity kinoEntity) {
        final Kino kino = new Kino(kinoEntity.id(), kinoEntity.version());
        Set<KinoSaal> mappedKinoSaele = kinoEntity.kinoSaele.stream()
                .map(kinoSaalEntity -> mapKinoSaal(kinoSaalEntity, kino))
                .collect(Collectors.toCollection(HashSet::new));

        kino.name = new Kino.Name(kinoEntity.name);
        kino.adresse = new Kino.Adresse(kinoEntity.adresse);
        kino.emailAdresse = new Kino.EmailAdresse(kinoEntity.emailAdresse);
        kino.kinoSaele = mappedKinoSaele;

        return kino;
    }

    @SuppressWarnings("OptionalUsedAsFieldOrParameterType")
    public static Optional<Kino> mapKino(final Optional<KinoEntity> optionalKinoEntity) {
        if (optionalKinoEntity.isEmpty()) {
            return Optional.empty();
        }
        else {
            KinoEntity kinoEntity = optionalKinoEntity.get();
            return Optional.of(mapKino(kinoEntity));
        }
    }

    public static KinoEntity mapKino(final Kino kino) {
        final KinoEntity kinoEntity = new KinoEntity(kino.id().id(), kino.version().version(),
                getRawOrNull(kino.name), getRawOrNull(kino.adresse), getRawOrNull(kino.emailAdresse));

        kinoEntity.kinoSaele = kino.kinoSaele.stream()
                .map(kinoSaal -> mapKinoSaal(kinoSaal, kinoEntity))
                .collect(Collectors.toCollection(HashSet::new));

        return kinoEntity;
    }

    @SuppressWarnings("OptionalUsedAsFieldOrParameterType")
    public static Optional<KinoSaal> mapToKinoSaal(final Optional<KinoSaalEntity> kinoSaalEntity) {
        return kinoSaalEntity.map(KinoKinoSaalEntity2KinoKinoSaalMapper::mapKinoSaal);
    }

    public static KinoSaal mapKinoSaal(final KinoSaalEntity kinoSaalEntity) {
        KinoEntity kinoEntity = kinoSaalEntity.kino;
        Kino mappedKino = mapKino(kinoEntity);
        return new KinoSaal(kinoSaalEntity.id(), kinoEntity.version(),
                new KinoSaal.Name(kinoSaalEntity.name), new KinoSaal.AnzahlPlaetze(kinoSaalEntity.anzahlPlaetze), mappedKino);
    }

    private static KinoSaal mapKinoSaal(final KinoSaalEntity kinoSaalEntity, final Kino kino) {
        return new KinoSaal(kinoSaalEntity.id(), kinoSaalEntity.version(),
                new KinoSaal.Name(kinoSaalEntity.name), new KinoSaal.AnzahlPlaetze(kinoSaalEntity.anzahlPlaetze), kino);
    }

    @SuppressWarnings({"OptionalUsedAsFieldOrParameterType", "unused"})
    public static Optional<KinoSaalEntity> mapFromKinoSaal(final Optional<KinoSaal> kinoSaal) {
        return kinoSaal.map(KinoKinoSaalEntity2KinoKinoSaalMapper::mapKinoSaal);
    }

    public static KinoSaalEntity mapKinoSaal(final KinoSaal kinoSaal) {
        Kino kino = kinoSaal.kino;
        KinoEntity mappedKino = mapKino(kino);
        return new KinoSaalEntity(kinoSaal.id().id(), kinoSaal.version().version(),
                getRawOrNull(kinoSaal.name), getRawOrNull(kinoSaal.anzahlPlaetze), mappedKino);
    }

    private static KinoSaalEntity mapKinoSaal(final KinoSaal kinoSaal, final KinoEntity kinoEntity) {
        return new KinoSaalEntity(kinoSaal.id().id(), kinoEntity.version().version(),
                getRawOrNull(kinoSaal.name), getRawOrNull(kinoSaal.anzahlPlaetze), kinoEntity);
    }
}
