package de.thpeetz.kontor.tysc.services;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicReference;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import de.thpeetz.kontor.tysc.data.FieldPosition;
import de.thpeetz.kontor.tysc.data.Player;
import de.thpeetz.kontor.tysc.data.Rooster;
import de.thpeetz.kontor.tysc.data.Sport;
import de.thpeetz.kontor.tysc.data.Team;
import de.thpeetz.kontor.tysc.repository.FieldPositionRepository;
import de.thpeetz.kontor.tysc.repository.PlayerRepository;
import de.thpeetz.kontor.tysc.repository.RoosterRepository;
import de.thpeetz.kontor.tysc.repository.SportRepository;
import de.thpeetz.kontor.tysc.repository.TeamRepository;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class SportService {

    @Autowired
    private SportRepository sportRepository;

    @Autowired
    private TeamRepository teamRepository;

    @Autowired
    private FieldPositionRepository fieldPositionRepository;

    @Autowired
    private PlayerRepository playerRepository;

    @Autowired
    private RoosterRepository roosterRepository;

    public List<Sport> findAllSports(String stringFilter) {
        if (stringFilter == null || stringFilter.isEmpty()) {
            return sportRepository.findAll();
        } else {
            return sportRepository.search(stringFilter);
        }
    }

    public void deleteSport(Sport sport) {
        sportRepository.delete(sport);
    }

    public Sport saveSport(Sport sport) {
        if (sport == null) {
            log.warn("Sport is null. Are you sure you have connected your form to the application?");
            return null;
        }
        return sportRepository.save(sport);
    }

    public List<Player> findAllPlayers(String stringFilter) {
        if (stringFilter == null || stringFilter.isEmpty()) {
            return playerRepository.findAll();
        } else {
            return playerRepository.search(stringFilter);
        }
    }

    public Player savePlayer(Player player) {
        if (player == null) {
            log.warn("Player is null. Are you sure you have connected yout form to the application?");
            return null;
        }
        return playerRepository.save(player);
    }

    public void deletePlayer(Player player) {
        playerRepository.delete(player);
    }

    public List<Team> findAllTeams(String stringFilter) {
        if (stringFilter == null || stringFilter.isEmpty()) {
            return teamRepository.findAll();
        } else {
            return teamRepository.search(stringFilter);
        }
    }

    public void deleteTeam(Team team) {
        teamRepository.delete(team);
    }

    public void saveTeam(Team team) {
        if (team == null) {
            log.warn("Team is null. Are you sure you have connected your form to the application?");
            return;
        }
        teamRepository.save(team);
    }

    public List<FieldPosition> findAllPositions(String stringFilter) {
        if (stringFilter == null || stringFilter.isEmpty()) {
            return fieldPositionRepository.findAll();
        } else {
            return fieldPositionRepository.search(stringFilter);
        }
    }

    public List<FieldPosition> findAllPositionsForSport(Sport sport) {
        if (sport == null) {
            return fieldPositionRepository.findAll();
        } else {
            log.info("Find positions for Sport: {}", sport);
            return fieldPositionRepository.findBySport(sport);
        }
    }

    public void savePosition(FieldPosition position) {
        if (position == null) {
            log.warn("Position is null. Are you sure you have connected your form to the application?");
            return;
        }
        fieldPositionRepository.save(position);
    }

    public void deletePosition(FieldPosition position) {
        fieldPositionRepository.delete(position);
    }

    public List<Rooster> findAllRoosters() {
        return roosterRepository.findAll();
    }

    public Rooster findRoosterByFields(Team team, Player player, FieldPosition position, Integer year) {
        return roosterRepository.findByReferences(player, team, position, year);
    }

    public void saveRooster(Rooster rooster) {
        if (rooster == null) {
            log.warn("");
            return;
        }
        roosterRepository.save(rooster);
    }

	public void deleteRooster(Rooster rooster) {
        roosterRepository.delete(rooster);
	}

    public String importData(Map<String, String> fields) {
        AtomicReference<String> status = new AtomicReference<>("unknown");
        String id = fields.get("id");
        Optional<Sport> optional = sportRepository.findById(id);
        if (optional.isEmpty()) {
            log.info(" not found: {} with {}", id, fields);
            status.set(id + "not found");
            Sport checkExisting = sportRepository.findByName(fields.get("name"));
            if (checkExisting != null) {
                log.info("entry already there with different id ({}), will be deleted", checkExisting.getId());
                deleteSport(checkExisting);
            }
            Sport sport = new Sport();
            sport.setId(id);
            sport.setName(fields.get("name"));
            sportRepository.save(sport);
        } else {
            optional.ifPresent( entry -> {
                log.info(" found: {}", entry.getName());
                String updateStatus = updateSportFields(entry, fields);
                sportRepository.save(entry);
                status.set(updateStatus);
            });
        }
        return status.get();
    }

    private String updateSportFields(Sport sport, Map<String, String> fields) {
        StringBuilder status = new StringBuilder();
        for (Map.Entry<String, String> entry : fields.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();
            switch (key) {
                case "id", "created_date", "last_modified_date", "version":
                    break;
                case "table_name":
                    status.append(sport.updateName(value));
                default:
                    log.info("field {} is unknown for table {}", key, sport.getClass().getName());
            }
        }
        return status.toString();
    }
}
