package io.teiler.server.services;

import io.teiler.server.dto.Compensation;
import io.teiler.server.dto.Debt;
import io.teiler.server.services.util.GroupUtil;
import io.teiler.server.services.util.settleup.PersonChooser;
import io.teiler.server.services.util.settleup.TopBottomChooser;
import java.util.LinkedList;
import java.util.List;
import java.util.SortedMap;
import java.util.TreeMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * Provides service-methods for suggested compensations.
 *
 * @author dthoma
 */
@Service
public class SuggestCompensationService {

    private static final Logger LOGGER = LoggerFactory.getLogger(SuggestCompensationService.class);

    private SortedMap<Integer, Debt> debts;

    @Autowired
    private GroupUtil groupUtil;

    @Autowired
    private DebtService debtService;

    /**
     * Gets the suggested compensations for this group.
     *
     * @param groupId The group to get the suggested compensations for.
     * @return The suggested compensations for this group
     */
    public List<Compensation> getSuggestedCompensations(String groupId) {
        groupUtil.checkIdExists(groupId);

        this.debts = new TreeMap<>();
        debtService.getDebts(groupId).stream().filter(d -> d.getBalance() != 0)
            .forEach(d -> this.debts.put(d.getBalance(), d));

        List<Compensation> suggestedCompensations = new LinkedList<>();
        PersonChooser personChooser = new TopBottomChooser(debts);

        while (personChooser.personsLeft()) {
            Debt creditor = personChooser.getNextCreditor();
            Debt debitor = personChooser.getNextDebitor();

            int newCreditorBalance;
            int newDebitorBalance;
            if (creditor.getBalance() >= debitor.getBalance()) {
                Compensation compensation = new Compensation(
                    null,
                    - debitor.getBalance(),
                    debitor.getPerson(),
                    creditor.getPerson()
                );
                suggestedCompensations.add(compensation);

                newCreditorBalance = creditor.getBalance() + debitor.getBalance();
                newDebitorBalance = 0;
            } else {
                Compensation compensation = new Compensation(
                    null,
                    creditor.getBalance(),
                    debitor.getPerson(),
                    creditor.getPerson()
                );
                suggestedCompensations.add(compensation);

                newCreditorBalance = 0;
                newDebitorBalance = debitor.getBalance() + creditor.getBalance();
            }
            updateDebts(newCreditorBalance, creditor);
            updateDebts(newDebitorBalance, debitor);
        }

        LOGGER.debug("View suggested compensations: {}", suggestedCompensations);
        return suggestedCompensations;
    }

    private void updateDebts(int newBalance, Debt debt) {
        this.debts.remove(debt.getBalance(), debt);
        debt.setBalance(newBalance);
        this.debts.put(newBalance, debt);
    }

}

@@ -1818,32 +1818,58 @@
 DebitorBalance;%0A
+            int balance;%0A%0A
             if (
@@ -1937,143 +1937,102 @@
     
-Compensation compensation = new Compensation(%0A                    null,%0A                    - debitor.getBalance(),%0A                   
+balance = -debitor.getBalance();%0A%0A                newCreditorBalance = creditor.getBalance() +
  deb
@@ -2035,33 +2035,34 @@
  debitor.get
-Person(),
+Balance();
 %0A           
@@ -2070,35 +2070,31 @@
     
-    creditor.getPerson()%0A  
+newDebitorBalance = 0;%0A
     
@@ -2093,36 +2093,40 @@
  0;%0A            
-  );
+%7D else %7B
 %0A               
@@ -2130,47 +2130,38 @@
     
-suggestedCompensations.add(compensation
+balance = creditor.getBalance(
 );%0A%0A
@@ -2197,39 +2197,54 @@
 lance = 
-creditor.get
+0;%0A                newDebitor
 Balance
-() +
+ =
  debitor
@@ -2260,47 +2260,32 @@
 ce()
-;%0A                newDebitor
+ + creditor.get
 Balance
- = 0
+()
 ;%0A  
@@ -2291,36 +2291,26 @@
            %7D
- else %7B%0A    
+%0A%0A
             
@@ -2371,20 +2371,16 @@
         
-    
 null,%0A  
@@ -2397,39 +2397,17 @@
     
-    creditor.getBalance(),%0A    
+balance,%0A
     
@@ -2439,20 +2439,16 @@
 rson(),%0A
-    
         
@@ -2492,19 +2492,11 @@
     
-    );%0A    
+);%0A
     
@@ -2550,144 +2550,8 @@
 );%0A%0A
-                newCreditorBalance = 0;%0A                newDebitorBalance = debitor.getBalance() + creditor.getBalance();%0A            %7D%0A
     

Consolidate algorithm