import java.util.ArrayList;
import java.util.Collections;

public class Sokkelo {
  private int[][] sokkelo;
  private int[][] eiKaydytPaikat;
  Pelaaja pelaaja;

  private int maaliX = -1;
  private int maaliY = -1;
  private ArrayList<Morko> morot;
  private ArrayList<Aarre> aarteet;
  private ArrayList<Portaali> portaalit;

  public Sokkelo(int[][] sokkelo) {
    this.sokkelo = sokkelo;
    this.eiKaydytPaikat = new int[sokkelo.length][sokkelo[0].length];
    
    this.aarteet = new ArrayList<Aarre>();
    this.portaalit = new ArrayList<Portaali>();
    this.morot = new ArrayList<Morko>();

    for (int rivi = 0; rivi < this.sokkelo.length; ++rivi) {
      for (int alkio = 0; alkio < this.sokkelo[rivi].length; ++alkio) {
        if(this.sokkelo[rivi][alkio] == 0) {
          this.eiKaydytPaikat[rivi][alkio] = 1;
        }
        
        if (this.sokkelo[rivi][alkio] == 2) {
          this.pelaaja = new Pelaaja(alkio, rivi);
          this.sokkelo[rivi][alkio] = 0;
        }

        if (this.sokkelo[rivi][alkio] == 3) {
          Aarre aarre = new Aarre(alkio, rivi);
          this.aarteet.add(aarre);
          this.sokkelo[rivi][alkio] = 0;
        }

        if (this.sokkelo[rivi][alkio] == 99) {
          Morko m = new Morko(this, alkio, rivi);
          this.morot.add(m);
          this.sokkelo[rivi][alkio] = 0;
        }
        
        if (this.sokkelo[rivi][alkio] == 4) {
          Portaali p = new Portaali(alkio, rivi);
          this.portaalit.add(p);
          this.sokkelo[rivi][alkio] = 0;
        }

        if (this.sokkelo[rivi][alkio] == -1) {
          this.maaliY = rivi;
          this.maaliX = alkio;
        }
      }
    }
  }
  
  public Pelaaja getPelaaja() {
    return pelaaja;
  }


  public boolean liiku(String suunta) {
    int uusiX = pelaaja.getX();
    int uusiY = pelaaja.getY();
    if ("o".equals(suunta)) {
      uusiX += 1;
    } else if ("v".equals(suunta)) {
      uusiX -= 1;
    } else if ("y".equals(suunta)) {
      uusiY -= 1;
    } else if ("a".equals(suunta)) {
      uusiY += 1;
    } else {
      System.out.println("Hyvin omituinen suunta: " + suunta);
    }

    if (voikoLiikkua(uusiX, uusiY)) {
      // boolean astuttiin portaaliin
      Portaali astuttu = null;
      for(Portaali p: portaalit) {
        if(p.onkoSijainnissa(uusiX, uusiY)) {
          astuttu = p;
        }
      }
      
      if(astuttu != null && portaalit.size() > 1) {
        Portaali uusiSijainti = null;
        Collections.shuffle(portaalit);
        uusiSijainti = portaalit.get(0);
        if(astuttu.equals(uusiSijainti)) {
          uusiSijainti = portaalit.get(1);
        }
        
        uusiX = uusiSijainti.getX();
        uusiY = uusiSijainti.getY();
      }
      
      pelaaja.liiku(uusiX, uusiY);
      if(this.eiKaydytPaikat[uusiY][uusiX] == 1) {
        this.eiKaydytPaikat[uusiY][uusiX] = 0;
        pelaaja.lisaaPisteita(1);
      }
    } else {
      return false; // ei voi liikkua
    }

    Aarre poistettavaAarre = null;
    for (Aarre aarre : aarteet) {
      
      if (aarre.onkoSijainnissa(pelaaja.getX(), pelaaja.getY())) {
        pelaaja.lisaaPisteita(aarre.getPisteet());
        poistettavaAarre = aarre;
      }
    }

    if (poistettavaAarre != null) {
      aarteet.remove(poistettavaAarre);
    }
    
    for(Morko morko: morot) {
      if (pelaaja.onkoSijainnissa(morko.getX(), morko.getY())) {
        pelaaja.vahennaPisteita(500);
        return true;
      }
      
      morko.liiku();
      if (pelaaja.onkoSijainnissa(morko.getX(), morko.getY())) {
        pelaaja.vahennaPisteita(500);
        return true;
      }  
    }
    
    return true;
  }

  public boolean voikoLiikkua(int x, int y) {
    boolean palautus = (sokkelo[y][x] == 0 || sokkelo[y][x] == -1);
    return palautus;
  }

  public boolean peliPaattyi() {
    return pelaajaMaalissa() || morkoSoi();
  }

  public boolean pelaajaMaalissa() {
    return pelaaja.onkoSijainnissa(maaliX, maaliY);
  }

  public boolean morkoSoi() {
    for(Morko morko: morot) { 
      if(pelaaja.onkoSijainnissa(morko.getX(), morko.getY())) {
        return true;
      }
    }
    return false;
  }
  
  public String toString() {
    String palautus = new String();

    for (int y = 0; y < sokkelo.length; y++) {
      for (int x = 0; x < sokkelo[y].length; x++) {
        palautus += annaRuudunSisalto(x, y);
      }
      palautus += "\n";
    }
    palautus += pelaaja.toString();

    return palautus;
  }
  
  private char annaRuudunSisalto(int x, int y) {
    for(Morko morko: morot) {
      if (morko.onkoSijainnissa(x, y)) {
        return morko.getMerkki();
      }
    }
    
    if (pelaaja.onkoSijainnissa(x, y)) {
      return pelaaja.getMerkki();
    }
    
    for(Portaali p: portaalit) {
      if(p.onkoSijainnissa(x, y)) {
        return p.getMerkki();
      }
    }
    
    for(Aarre a: aarteet) {
      if(a.onkoSijainnissa(x, y)) {
        return a.getMerkki();
      }
    }
    
    if(sokkelo[y][x] == -1) {
      // maali
      return 'M';
    }  else if (sokkelo[y][x] == 1) {
      // seinä
      return 'X';
    }
    
    // vapaa, ei käyty
    if(this.eiKaydytPaikat[y][x] == 1) {
      return '.';
    }
    // vapaa, käyty
    return ' ';
  }
}