package worms.model;

import java.util.*;

import worms.util.IllegalNameException;
import worms.util.TeamComparator;

public class Team {
    // region constructor
    //===================================================================================
	
    public Team (String name) {
        setName(name);
        this.wormCollection = new TreeSet<>(new TeamComparator());
    }
	
    //===================================================================================
    // endregion
	
    // region changesTeam
    //===================================================================================

    /**
     * @param worm
     * 
     * @post ...
     * 		 |new.team = old.team + Worm... worm
     * 
     * @throws IllegalArgumentException
     */
	public void addWorm(Worm... worm) throws IllegalArgumentException {
	    if (worm == null) throw new IllegalArgumentException();
		for (Worm w: worm) {
			if (w != null && canHaveAsWorm(w)) {
                getAllWormsOfTeam().add(w);
                w.setTeam(this);
			}
			else {
				throw new IllegalArgumentException();
			}
		}
	}
	
	/**
	 * @param worm ..
	 * 
	 * @return
	 * 			|for each i in [0,team.size()[
	 * 			|	result == (worm.getMass() > getMinMassTeam()/2 && worm.getMass() < 2 * getMaxMassTeam() 
	 * 			|	&& worm.isAlive() && (team.get(i)).getName() != worm.getName())
	 */
	private boolean canHaveAsWorm(Worm worm) throws IllegalArgumentException {

	    if (worm == null) throw new IllegalArgumentException();

	    Collection<Worm> worms = getAllWormsOfTeam();
	    if (worms.size() == 0 && !worm.isTerminated()) return true;

		if (worm.getMass() >= getMinMassTeam() / 2 && worm.getMass() <= 2 * getMinMassTeam()
				&& !worm.isTerminated()) {
            for (Worm elWorm : worms) {
                if (elWorm.getName().equals(worm.getName())) return false;
            }
			return true;
		}
		return false;
	}

	/**
	 * @param worm
	 * 
	 * @post ...
	 * 		 |(new.team).contains(Worm... worm) == false
	 */
	public void removeWormsFromTeam(Worm... worm) throws IllegalArgumentException {

	    if (worm == null) throw new IllegalArgumentException();
		for (Worm w: worm) {
		    if (w == null) throw new IllegalArgumentException();
            getAllWormsOfTeam().remove(w);
            w.setTeam(null);
		}
	}

	/**
	 * @param worm ...
	 * 
	 * @return	...
	 * 			|result == team.contains(worm)
	 */
	public boolean containsWorm(Worm worm) throws IllegalArgumentException {
	    if (worm == null) throw new IllegalArgumentException();
		return getAllWormsOfTeam().contains(worm);
	}

	public Collection<Worm> getAllWormsOfTeam() {
		return wormCollection;
	}

	public int getNbWorms() {
	    return getAllWormsOfTeam().size();
    }

	/**
	 * @param receivingTeam ...
	 * @param supplyingTeam ...
	 * 
	 * @post ... (NOG NIET ZEKER VAN)
	 * 		 |recevingTeam == receivingTeam + supplyingTeam
	 * @post ...
	 * 		 |supplyingTeam.isTerminated() == true
	 */
    public static void mergeTeams(Team receivingTeam, Team supplyingTeam) throws IllegalArgumentException {

        if (receivingTeam == null || supplyingTeam == null || receivingTeam.equals(supplyingTeam) ) {
            throw new IllegalArgumentException();
        }

    	Worm[] supWorms = supplyingTeam.getAllWormsOfTeam().toArray(new Worm[0]);
    	receivingTeam.addWorm(supWorms);
    	supplyingTeam.removeWormsFromTeam(supWorms);
    }
	
	private Collection<Worm> wormCollection;
	
	//===================================================================================
    // endregion
	
	// region mass
    //===================================================================================

	/**
	 * @return	...
	 */
	private double getMinMassTeam() throws IllegalStateException {
        Worm minMass = getAllWormsOfTeam().stream().min(Comparator.comparingDouble(Worm::getMass)).orElse(null);
	    if (minMass == null) {
            throw new IllegalStateException();
        }
        return minMass.getMass();
	}
	
	//===================================================================================
    // endregion
	
	// region name
    //===================================================================================
	
	/**
	 * @return	...
	 * 			|result == this.name
	 */
	public String getName() {
		return this.name;
	}


	/**
	 * @param name ...
	 * 
	 * @post |new.getName() == name
	 * 
	 * @throws IllegalNameException
	 * 		   |! isValidName(name)
	 */
	public void setName(String name) throws IllegalNameException {

        int validTeamName = Worm.isValidName(name);
        if (validTeamName != -1)
            throw new IllegalNameException(validTeamName, name);

        this.name = name;
    }

	private String name;
	
	//===================================================================================
    // endregion
	
	// region terminate
    //===================================================================================
	
	/**
     *
	 * @post
	 * 		 |new.terminate == true
	 */
    public void terminate() {
    	this.terminated = true;
    }
	
    /**
     * 
     * @return	...
     * 		 	|if terminate == true
     * 			|	result == true
     * 			|else
     * 			|	result == false
     */
    public boolean isTerminated() {
        return this.terminated;
    }
    
    private boolean terminated = false;
    
    //===================================================================================
    // endregion
}
