import java.util.*;

/**
 * Segmento di via compreso tra due snodi, ha i due punti 
 * estremi, uno spessore, il nome della via, gli intervalli di
 * numeri civici sul lato pari e su quello dispari.
 * Memorizza anche le infrastrutture presenti.
 */
public class SegmentoVia implements EntitaConNome
{
  /** Nome della via. */ protected String nome;
  /** Punto iniziale. */ public Snodo p1;
  /** Punto finale. */ public Snodo p2;
  /** Spessore del segmento. */ public double spessore;
  /** Minimo numero civico sul lato pari. */ public int pari1;
  /** Massimo numero civico sul lato pari. */ public int pari2;
  /** Minimo numero civico sul lato dispari. */ public int dispari1;
  /** Massimo  numero civico sul lato dispari. */ public int dispari2;

  /** Infrastrutture contenute in questo segmento di via. */
  protected Vector infras = new Vector();
  /** Numero di infrastrutture contenute in questo segmento di via. */
  protected int numInfras = 0;

  /** Ritorna il nome della via a cui questo segmento appartiene. */
  public String ilNome() { return nome; }
  /** Cambia il nome della via a cui questo segmento appartiene. */
  public void cambiaNome(String n) { nome = n; }

  /** Crea segmento di via con estremi dati, senza nome, con spessore
      zero e numeri civici tutti zero. */
  public SegmentoVia(Snodo pp1, Snodo pp2) {  p1 = pp1; p2 = pp2;  }

  /** Aggiunge una infrastruttura. */
  public void aggiungi(Infrastruttura is)
  {  infras.addElement((Object)is);  numInfras++;  }

  /** Toglie una infrastruttura. */
    public void togli(Infrastruttura is)
  {  if (infras.removeElement((Object)is)) numInfras--;  }

  /** Ritorna il numero di infrastrutture. */
  public int numeroInfrastrutture() { return numInfras;  }
  
  /** Ritorna l'infrastruttura i-esima. */
  public Infrastruttura infrastruttura(int i) 
  {
     if ((i<0)||(i>numInfras)) return null;
     return (Infrastruttura)infras.elementAt(i);
  }

  /**
   * Controlla se questo segmento interseca propriamente il segmento
   * orizzontale di estremi q1 e q2, non dovrebbe servire nel progetto.
   */
  public boolean intersecaOrizzontale(Punto q1, Punto q2)
  {
    double unicaX = q1.x; // q2.x sarebbe uguale
    if ( (p1.x<=unicaX) && (p2.x<=unicaX) ) return false;
    if ( (p1.x>=unicaX) && (p2.x>=unicaX) ) return false;
    int svolta1 = Punto.svolta(q1,p1,p2);
    int svolta2 = Punto.svolta(q2,p1,p2);
    if ( (svolta1==Punto.DESTRA) && (svolta2==Punto.SINISTRA) )
       return true;
    if ( (svolta1==Punto.SINISTRA) && (svolta2==Punto.DESTRA) )
       return true;
    return false;
  }

  /**
   * Controlla se questo segmento interseca propriamente il segmento
   * verticale di estremi q1 e q2, non dovrebbe servire nel progetto.
   */
  public boolean intersecaVerticale(Punto q1, Punto q2)
  {
    double unicaY = q1.y; // q2.y sarebbe uguale
    if ( (p1.y<=unicaY) && (p2.y<=unicaY) ) return false;
    if ( (p1.y>=unicaY) && (p2.y>=unicaY) ) return false;
    int svolta1 = Punto.svolta(q1,p1,p2);
    int svolta2 = Punto.svolta(q2,p1,p2);
    if ( (svolta1==Punto.DESTRA) && (svolta2==Punto.SINISTRA) ) return true;
    if ( (svolta1==Punto.SINISTRA) && (svolta2==Punto.DESTRA) ) return true;
    return false;
  }

  /**
   * Controlla se questo segmento interseca il quadrante di
   * diagonale (x1,y1)-(x2,y2), dove (x1,y1) e' l'angolo di x,y 
   * minime e (x2,y2) e' l'angolo di x,y massime.
   */
  public boolean inQuadrante(double x1, double y1, double x2, double y2)
  {
    if ( (p1.x<x1) && (p2.x<x1) ) return false; // tutto a sx
    if ( (p1.x>x2) && (p2.x>x2) ) return false; // tutto a dx
    if ( (p1.y<y1) && (p2.y<y1) ) return false; // tutto a sotto
    if ( (p1.y>y2) && (p2.y>y2) ) return false; // tutto a sopra
                  
    if ( (p1.x>x1) && (p1.x<x2) && (p1.y>y1) && (p1.y<y2) )
    return true; // estremo p1 dentro
    if ( (p2.x>x1) && (p2.x<x2) && (p2.y>y1) && (p2.y<y2) ) 
    return true; // estremo p2 dentro

    // controlla se interseca retta orizzontale x= x1
    if ( intersecaOrizzontale(new Punto(x1,y1), new Punto(x1,y2)) )
       return true;
    // controlla se interseca retta orizzontale x= x2
    if ( intersecaOrizzontale(new Punto(x2,y1), new Punto(x2,y2)) )
       return true;
    // controlla se interseca retta verticale y= y1     
    if ( intersecaVerticale(new Punto(x1,y1), new Punto(x2,y1)) )
       return true;
    // controlla se interseca retta verticale y= y2
    if ( intersecaVerticale(new Punto(x1,y2), new Punto (x1,y2)) )
       return true;
    return false;
  }   

  /** Controlla se il nome della via di questo segmento
      e' quello dato. */
  public boolean corrisponde(String nomeVia)
  {  return (nomeVia.compareTo(nome)==0);  }

  /** Controlla se il nome della via corrisponde e se questo
      segmento contiene il numero civico voluto. */
  public boolean corrisponde(String nomeVia, int n)
  {  
    if (nomeVia.compareTo(nome)==0) 
    {
      switch (n % 2)
      {
        case 0: return ( (pari1<=n) && (n<=pari2) );
        case 1: return ( (dispari1<=n) && (n<=dispari2) );
      }
    }
    return false;
  }

}
