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

public class Morko extends Hahmo {
  private Sokkelo sokkelo;

  // 0 = ylos, 1 = oikealle, 2 = alas, 3 = vasemmalle
  private int suunta;

  public Morko(Sokkelo sokkelo, int x, int y) {
    super(x, y, 'W');
    this.sokkelo = sokkelo;
  }

  public void liiku() {
    // vaihdetaan suuntaa risteyskohdassa
    if(onkoRisteysKohta()) {
      vaihdaSuuntaa();
    }
    
    // liikutaan suuntaan
    if(liikuSuuntaan()) {
      return;      
    }
    
    // jos liikkuminen jostain syystä epäonnistuu
    // yritetään vielä vaihtaa suuntaa ja liikkua.
    vaihdaSuuntaa();
    liikuSuuntaan();
    
    
    // vanhaa koodia, pelaajaa kohti meneminen
    /*
    int xMuutos = 0;
    int yMuutos = 0;

    if (!onkoRisteysKohta()) {
      if (suunta == 0) {
        yMuutos = 1;
      } else if (suunta == 1) {
        xMuutos = 1;
      } else if (suunta == 2) {
        yMuutos = -1;
      } else if (suunta == 3) {
        xMuutos = -1;
      }
    }

    // Reitti pelaajan luo. Otetaan ensiksi
    // pelaajan koordinaatit sokkelosta, jonka
    // jälkeen tutkitaan onko pelaaja kauempana
    // x vai y-akselilla. Tämän jälkeen pyritään
    // liikkumaan pelaajan suuntaan.
    int pelaajaX = sokkelo.getPelaaja().getX();
    int pelaajaY = sokkelo.getPelaaja().getY();

    int xErotus = Math.abs(pelaajaX - this.x);
    int yErotus = Math.abs(pelaajaY - this.y);

    if (yErotus > xErotus) {
      // pyritään liikkumaan y-akselilla
      // mennään aina pelaajaa kohti ->
      // jos pelaajan koordinaatti on suurempi kuin
      // oma koordinaatti, pyritään kasvattamaan
      // omaa koordinaattia

      if (pelaajaY > this.y) {
        yMuutos = 1;
      } else {
        yMuutos = -1;
      }
    } else {
      // pyritään liikkumaan x-akselilla
      if (pelaajaX > this.x) {
        xMuutos = 1;
      } else {
        xMuutos = -1;
      }
    }

    System.out.println("Xmuutos: " + xMuutos);
    System.out.println("YMuutos: " + yMuutos);

    // jos ei voida liikkua haluttuun suuntaan, valitaan satunnianen
    // suunta
    while (!sokkelo.voikoLiikkua(this.x + xMuutos, this.y + yMuutos)) {
      int i = new Double(Math.random() * 4).intValue();
      xMuutos = 0;
      yMuutos = 0;

      if (i == 0) {
        xMuutos = 1;
      } else if (i == 1) {
        xMuutos = -1;
      } else if (i == 2) {
        yMuutos = 1;
      } else if (i == 3) {
        yMuutos = -1;
      }
    }

    this.x += xMuutos;
    this.y += yMuutos;
    */
  }

  // palauttaa true jos haluttuun suuntaan liikkuminen onnistui
  // ja emme ole risteyksessä
  private boolean liikuSuuntaan() {
    int xMuutos = 0;
    int yMuutos = 0;
    if (suunta == 0) {
      yMuutos = -1;
    } else if (suunta == 1) {
      xMuutos = 1;
    } else if (suunta == 2) {
      yMuutos = 1;
    } else if (suunta == 3) {
      xMuutos = -1;
    }

    if(sokkelo.voikoLiikkua(this.x + xMuutos, this.y + yMuutos)) {
      this.liiku(this.x + xMuutos, this.y + yMuutos);
      return true;
    }
    
    return false;
  }

  private boolean onkoRisteysKohta() {
    return (vapaatSuunnat().size() > 2);
  }
  
  private void vaihdaSuuntaa() {
    ArrayList<Integer> suunnat = vapaatSuunnat();
    if(Math.random() > 0.5) {
      int pelaajaSuunnassa = pelaajaSuunnassa();
      if(suunnat.contains(pelaajaSuunnassa)) {
        suunta = pelaajaSuunnassa;
        return;
      }
    }    
    
    // satunnaiseen suuntaan
    Collections.shuffle(suunnat);
    suunta = suunnat.get(0);
  }

  // 0 = ylos, 1 = oikealle, 2 = alas, 3 = vasemmalle
  private ArrayList<Integer> vapaatSuunnat() {
    ArrayList<Integer> vapaatSuunnat = new ArrayList<Integer>();
    if (sokkelo.voikoLiikkua(this.x + 1, this.y)) {
      vapaatSuunnat.add(1);
    }
    
    if (sokkelo.voikoLiikkua(this.x - 1, this.y)) {
      vapaatSuunnat.add(3);
    }
    
    if (sokkelo.voikoLiikkua(this.x, this.y + 1)) {
      vapaatSuunnat.add(2);
    }
    
    if (sokkelo.voikoLiikkua(this.x, this.y - 1)) {
      vapaatSuunnat.add(0);
    }
    
    return vapaatSuunnat;
  }
  
  private int pelaajaSuunnassa() {
    int pelaajaX = sokkelo.getPelaaja().getX();
    int pelaajaY = sokkelo.getPelaaja().getY();

    int xErotus = Math.abs(pelaajaX - this.x);
    int yErotus = Math.abs(pelaajaY - this.y);

    // 0 = ylos, 1 = oikealle, 2 = alas, 3 = vasemmalle
    if (yErotus > xErotus) {
      if (pelaajaY > this.y) {
        return 2;
      } else {
        return 0;
      }
    } else {
      // pyritään liikkumaan x-akselilla
      if (pelaajaX > this.x) {
        return 1;
      } else {
        return 3;
      }
    }
  }
}
