package io.teiler.server.persistence.entities;

import io.teiler.server.dto.Group;
import io.teiler.server.dto.Person;
import io.teiler.server.util.TimeUtil;
import io.teiler.server.util.enums.Currency;

import java.sql.Timestamp;
import java.time.Instant;
import java.util.LinkedList;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.PrePersist;
import javax.persistence.PreUpdate;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;

/**
 * Entity representing an entry of the <code>group</code>-table.
 *
 * @author lroellin
 */
@Entity
@Table(name = "`group`") // f*** PSQL
public class GroupEntity {
    
    @Id
    @Column(name = "id")
    private String id;

    @NotNull
    @Column(name = "name")
    private String name;

    @NotNull
    @Enumerated(EnumType.STRING)
    @Column(name = "currency")
    private Currency currency;

    @OneToMany(targetEntity = PersonEntity.class, fetch = FetchType.EAGER, orphanRemoval = true)
    @JoinColumn(name = "`group`", referencedColumnName = "id")
    private List<PersonEntity> people;

    @NotNull
    @Column(name = "update_time")
    private Timestamp updateTime;

    @NotNull
    @Column(name = "create_time")
    private Timestamp createTime;

    public GroupEntity() { /* intentionally empty */ }

    /**
     * Converts a {@link GroupEntity} to a {@link Group}.
     * 
     * @param group {@link Group}
     */
    public GroupEntity(Group group) {
        List<PersonEntity> peopleEntities = new LinkedList<>();
        if (group.getPeople() != null) {
            for (Person person : group.getPeople()) {
                peopleEntities.add(new PersonEntity(person));
            }
        } else {
            peopleEntities = null;
        }
        this.id = group.getId();
        this.name = group.getName();
        this.currency = group.getCurrency();
        this.people = peopleEntities;
        this.updateTime = TimeUtil.convertToTimestamp(group.getUpdateTime());
        this.createTime = TimeUtil.convertToTimestamp(group.getCreateTime());
    }

    /**
     * Sets the update-time and creation-time to {@link Instant#now()}.
     * <br>
     * <i>Note:</i> The creation-time will only be set if it has not been set previously. 
     */
    @PreUpdate
    @PrePersist
    public void updateTimeStamps() {
        updateTime = new Timestamp(Instant.now().toEpochMilli());
        if (createTime == null) {
            createTime = updateTime;
        }
    }

    /**
     * Converts this {@link GroupEntity} to a {@link Group}.
     * 
     * @return {@link Group}
     */
    public Group toGroup() {
        List<Person> dtoPeople = new LinkedList<>();
        if (this.getPeople() != null) {
            for (PersonEntity personEntity : this.getPeople()) {
                dtoPeople.add(personEntity.toPerson());
            }
        } else {
            dtoPeople = null;
        }
        return new Group(
            this.getId(),
            this.getName(),
            this.getCurrency(),
            dtoPeople,
            TimeUtil.convertToLocalDateTime(this.getUpdateTime()),
            TimeUtil.convertToLocalDateTime(this.getCreateTime()));
    }

    public void addPerson(PersonEntity person) {
        people.add(person);
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Currency getCurrency() {
        return currency;
    }

    public void setCurrency(Currency currency) {
        this.currency = currency;
    }

    public List<PersonEntity> getPeople() {
        return people;
    }

    public void setPeople(List<PersonEntity> people) {
        this.people = people;
    }

    public Timestamp getCreateTime() {
        return new Timestamp(createTime.getTime());
    }

    public void setCreateTime(Timestamp createTime) {
        this.createTime = updateTime != null ? new Timestamp(createTime.getTime()) : null;
    }

    public Timestamp getUpdateTime() {
        return new Timestamp(updateTime.getTime());
    }

    public void setUpdateTime(Timestamp updateTime) {
        this.updateTime = updateTime != null ? new Timestamp(updateTime.getTime()) : null;
    }

    @Override
    public String toString() {
        return this.toGroup().toString();
    }
    
}

@@ -47,169 +47,8 @@
 %0D%0A%0D%0A
-import io.teiler.server.dto.Group;%0D%0Aimport io.teiler.server.dto.Person;%0D%0Aimport io.teiler.server.util.TimeUtil;%0D%0Aimport io.teiler.server.util.enums.Currency;%0D%0A%0D%0A
 impo
@@ -148,24 +148,63 @@
 util.List;%0D%0A
+import java.util.stream.Collectors;%0D%0A%0D%0A
 import javax
@@ -631,16 +631,177 @@
 ull;%0D%0A%0D%0A
+import io.teiler.server.dto.Group;%0D%0Aimport io.teiler.server.dto.Person;%0D%0Aimport io.teiler.server.util.TimeUtil;%0D%0Aimport io.teiler.server.util.enums.Currency;%0D%0A%0D%0A
 /**%0D%0A * 
@@ -1937,109 +1937,125 @@
     
-for (Person person : group.getPeople()) %7B%0D%0A                peopleEntities.add(new PersonEntity(person
+peopleEntities =%0D%0A                group.getPeople().stream().map(p -%3E new PersonEntity(p)).collect(Collectors.toList(
 ));%0D
@@ -2059,33 +2059,32 @@
 );%0D%0A            
-%7D
 %0D%0A        %7D else
@@ -3100,21 +3100,16 @@
     if (
-this.
 getPeopl
@@ -3140,60 +3140,19 @@
     
-for (PersonEntity personEntity : this.get
+dto
 People
-()) %7B
+ =
 %0D%0A  
@@ -3169,23 +3169,34 @@
     
-dto
+get
 People
-.add(p
+().stream().map(P
 erso
@@ -3206,17 +3206,18 @@
 tity
-.
+::
 toPerson
 ());
@@ -3216,27 +3216,39 @@
 rson
-());%0D%0A            %7D
+).collect(Collectors.toList());
 %0D%0A  
@@ -3344,21 +3344,16 @@
         
-this.
 getId(),
@@ -3366,21 +3366,16 @@
         
-this.
 getName(
@@ -3390,21 +3390,16 @@
         
-this.
 getCurre
@@ -3474,21 +3474,16 @@
 ateTime(
-this.
 getUpdat
@@ -3537,21 +3537,16 @@
 ateTime(
-this.
 getCreat

put them lambdas in there