package com.uca.flights;

import java.util.Collection;
import java.util.List;
import java.util.ArrayList;

/**
 * Represent an airport
 * @Author Cesano Ugo, Colmerauer Clément
 * 
 */
public class Airport {
    /**Airport name*/
    private String     name;
    /**Airport identifier*/
    private AirportId  id;
    /**Airport list of served cities*/
    private List<City> servedCities;
    /**Airport main city*/
    private City       mainCity;

    /**
     * Constructor
     * @param mainCity the city in which the airport is
     * @param id a string used to create the airport id
     * @param name the airport name
     * @throws IllegalArgumentException on null or empty parameter
     */
    public Airport(City mainCity, String id, String name) {
        if(mainCity == null)
        {
            throw new IllegalArgumentException("City can't be null.");
        }
        if(id == null)
        {
            throw new IllegalArgumentException("Id can't be null");
        }
        if(name == null)
        {
            throw new IllegalArgumentException("Name can't be null.");
        }
        if(id.trim().isEmpty())
        {
            throw new IllegalArgumentException("Id can't be uniquely space characters.");
        }
        if(name.trim().isEmpty())
        {
            throw new IllegalArgumentException("Name can't be uniquely space characters.");
        }

        this.id           = new AirportId(id);
        this.name         = name;
        this.servedCities = new ArrayList<City>();
        this.mainCity     = mainCity;
        this.servedCities.add(mainCity);
        mainCity.addAirportNonRec(this);
    }

    /**
     * Constructor
     * @param mainCity the city in which the airport is
     * @param id the airport identifier
     * @param name the airport name
     * @throws IllegalArgumentException on null or empty parameter
     */
    public Airport(City mainCity, AirportId id, String name) {
        if(mainCity == null)
        {
            throw new IllegalArgumentException("City can't be null.");
        }
        if(id == null)
        {
            throw new IllegalArgumentException("Id can't be null");
        }
        if(name == null)
        {
            throw new IllegalArgumentException("Name can't be null.");
        }
        if(name.trim().isEmpty())
        {
            throw new IllegalArgumentException("Name can't be uniquely space characters.");
        }

        this.servedCities = new ArrayList<City>();
        this.mainCity     = mainCity;
        this.name         = name;
        this.servedCities.add(mainCity);
        mainCity.addAirportNonRec(this);
    }

    /**
     * Getter
     * @return airport name
     */
    public String getName() {
        return name;
    }

    /**
     * Getter
     * @return airport main city
     */
    public City getMainCity()
    {
        return this.mainCity;
    }

    /**
     * Setter
     * @param name the airport name
     * @throws IllegalArgumentException on null or empty parameter
     */
    public void setName(String name) 
    {
        if(name == null)
        {
            throw new IllegalArgumentException("Name can't be null.");
        }
        if(name.trim().isEmpty())
        {
            throw new IllegalArgumentException("Name can't be uniquely space characters.");
        }
        this.name = name;
    }

    /**
     * Getter
     * @return airport id
     */
    public AirportId getId()
    {
        return this.id;
    }

    /**
     * Getter
     * @return a shallow copy of the airport list of served city
     */
    public Collection<City> getServedCity()
    {
        return new ArrayList<City>(this.servedCities);
    }

    /**
     * Add a city to the airport list of served city
     * @param city the city to add, warning on already existing city
     * @throws IllegalArgumentException on null parameter
     */
    public void addCity(City city)
    {
        if(city == null)
        {
            throw new IllegalArgumentException("City can't be null.");
        }
        if(!this.servedCities.contains(city))
        {
            this.servedCities.add(city);
            city.addAirport(this);
        }
        else
        {
            System.err.println("City already served");
        }
    }

    /**
     * Remove a city to the airport list of served city
     * @param city the city to remove
     * @throws IllegalArgumentException on null, inextistant or mainCity parameter
     */
    public void removeCity(City city)
    {
        if(city == null)
        {
            throw new IllegalArgumentException("City can't be null.");
        }
        if(city.equals(this.mainCity))
        {
            throw new IllegalArgumentException("Can't remove main city");
        }
        else if(!this.servedCities.contains(city))
        {
            throw new IllegalArgumentException("City isn't served");
        }
        else 
        {
            city.removeAirport(this);
        }
    }

    /**
     * Remove a city to the airport list of served city, non recursive to prevent double navigability infinite loop
     * @param city the city to remove
     * @throws IllegalArgumentException on null, inextistant or mainCity parameter
     */
    void removeCityNonRec(City city)
    {
        if(city == null)
        {
            throw new IllegalArgumentException("City can't be null.");
        }
        if(city.equals(this.mainCity))
        {
            throw new IllegalArgumentException("Can't remove main city");
        }
        if(this.servedCities.contains(city))
        {
            this.servedCities.remove(city);
        }
        else
        {
            throw new IllegalArgumentException("City isn't served");
        }
    }

    /**
     * Redefinition of equals
     * @param other the airport to compare to
     * @return true if other has the same identifier, false else
     * @throws IllegalArgumentException on null or not airport parameter
     */
    @Override 
    public boolean equals(Object other)
    {
        if(other == null)
        {
            throw new IllegalArgumentException("Airport can't be null.");
        }
        if(!(other instanceof Airport))
        {
            throw new IllegalArgumentException("Must be compared with airport.");           
        }
        Airport a = (Airport)other;
        return this.id == a.getId();
    }

    /**
     * Redefinition of hashCode
     * @return the hashcode
     */
    @Override
    public int hashCode()
    {
        return this.id == null ? 0 : this.id.length();
    }

    /**
     * Redefinition of toString
     * @return a string with name and identifier
     */
    @Override
    public String toString()
    {
        return this.name + "-" + this.id.toString();
    }
 }
