package inn.ocsf.bee.freigeld.core.data

import inn.ocsf.bee.freigeld.core.model.*
import inn.ocsf.bee.freigeld.core.model.data.PersonData
import inn.ocsf.bee.freigeld.core.model.data.QPersonData
import inn.ocsf.bee.freigeld.core.repo.PersonRepository
import org.slf4j.LoggerFactory
import org.springframework.stereotype.Service
import java.util.*
import java.util.stream.Collectors
import javax.annotation.PostConstruct
import javax.inject.Inject

@Service
class GlobalWorldImpl : GlobalWorld {

    @Inject
    private lateinit var personRepo: PersonRepository

    private val log = LoggerFactory.getLogger(javaClass)

    @PostConstruct
    fun init() {
        //personRepo.deleteAll()
    }

    override fun addPerson(person: Person): UUID {
        return personRepo.findOneByPersonId(person.id!!).map { it.person.id }.orElseGet {
            val pd = PersonData()
            when (person) {
                is NaturalPerson -> {
                    pd.person = person
                    pd.personType = PersonType.natural
                }
                is PrivatePerson -> {
                    pd.person = person
                    pd.personType = PersonType.privotal
                }
                else -> throw RuntimeException("unsupported person type ${person.javaClass.name}")
            }
            personRepo.save(pd).person.id
        }
    }

    override fun getPersonByIdentity(id: PersonIdentity): Person? {
        return personRepo.findOne(QPersonData.personData.identitySet.contains(id.key)).map { it.person }.orElse(null)
    }

    override fun setPersonIdentity(person: Person, identity: PersonIdentity) {
        val pd = personRepo.findOneByPersonId(person.id).orElseThrow { RuntimeException("person ${person.id} not found") }
        pd.identities.put(identity.key, identity)
        pd.identitySet = pd.identities.keys.toList()
        personRepo.save(pd)
    }

    override fun getPersonIdentitySet(person: Person): Set<PersonIdentity>? {
        return personRepo.findOneByPersonId(person.id).map { it.identities.values.toSet() }.orElse(null)
    }

    override fun getPerson(personId: UUID): Person? {
        return personRepo.findOneByPersonId(personId).map { it.person }.orElse(null)
    }

    override fun getPersonIds(): Set<UUID> {
        return personRepo.findAllBy().map { it.person.id }.collect(Collectors.toSet())
    }
}