/*
 * Idozito.java
 * az abszolút időtől nem csúszó, periodikus időzítést valósít meg
 * by pts@fazekas.hu at 2001.03.??
 * további doksi: a README-ben és e file legkülső class-ának fejkommentjében
 *
 * Kincskereső Kisgömböc (C) Early May 2001 by eNTitánok (Rév Szilvia,
 * Szabó Péter <pts@inf.bme.hu>, Szurdi Miklós, Weizengruber Attila).
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or   
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the  
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package eNTitanok.util;

/**
 * Egy vagy több, <code>Idozito.Idozitett</code> típusú objektum periodikus
 * időzítését
 * látja el, ügyelve arra, hogy hosszútávon se csússzunk el az abszolút időtől.
 * Csak egyetlen Idozitett-re teszteltük. Csak Win32 alatt működik jól, Linux
 * JDK1.3 alatt igenis csúszunk (,,lassulunk'', elmaradunk)
 * @see eNTitanok.util.Idozito.Idozitett
 */
public class Idozito extends Thread {
  protected volatile boolean futunk_e_meg=true;
  // volatile int hatravan; // volatile: ne cache-elje
  protected volatile long holtart;
  protected volatile int varakozok;
  protected long interval_ms;

  public Idozito(int interval_ms_) { interval_ms=interval_ms_; }

  public int getInterval() { return (int)interval_ms; }
  public long getHoltart() { return holtart; }

  public void var(long meddig) {
    // kívülről hivandó, pl :Időzített-ből
    do { // általában csak egyszer fut le a ciklusmag
      synchronized(this) {
        varakozok++;
        try { super.wait(interval_ms)} catch (InterruptedException e) { }
        varakozok--;
      }
    } while (meddig>holtart);
  }

  public static void alszik(int mennyit) {
    // millisec
    try { Thread.sleep(mennyit)} catch (InterruptedException e) {}
  }

  public void stopp() { futunk_e_meg=falsethis.interrupt()}
  public void run() {
    long logik, van, mennyit_alszom;
    this.setPriority(MAX_PRIORITY);
    mennyit_alszom=interval_ms;
    logik=java.lang.System.currentTimeMillis();
    while (futunk_e_meg) {
      // System.out.println("Mennyit: "+mennyit_alszom+".");
      try { java.lang.Thread.sleep(mennyit_alszom)} catch (InterruptedException e) { System.out.println("IR")}
      logik+=interval_ms;
      van=java.lang.System.currentTimeMillis();
      if (logik<van-200) mennyit_alszom=interval_ms*9/10;
      else if (logik>van+200) mennyit_alszom=interval_ms;
      //hatravan++;
      holtart++;
      if (varakozok>0) { synchronized(this) { super.notifyAll()} }
    }
  } /// run()

  public static class Idozitett {
    protected Idozito idozito;
    protected long megteve;
    protected boolean utoljara_aludtunk;
    protected long nem_rajzoltunk; // az utolsó rajzolás óta hányszor nem rajzoltunk
    protected long nem_rajzoltunk_osszesen;
    protected long rajzoltunk_osszesen;
    protected long mikor_inditottak; // időpont ms-ben

    public Idozitett(Idozito idozito) {
      this.idozito=idozito;
      ujraindit();
    }
    public boolean altass_el() {
      if (megteve++<idozito.getHoltart()) {
        Thread.yield();
        return utoljara_aludtunk=false;
      } else {
        idozito.var(megteve);
        return utoljara_aludtunk=true;
      }
    } /// altass_el()
    public void lassu_muvelet() {
      rajzoltunk_osszesen++;
      nem_rajzoltunk=0;
      altass_el();
    }
    public void gyors_muvelet() {
      nem_rajzoltunk++;
      nem_rajzoltunk_osszesen++;
      altass_el();
    }
    public boolean lehet_lassu_muvelet() { // állapotlekérdezés
      return utoljara_aludtunk || nem_rajzoltunk>50;
    }
    public void ujraindit() {
      utoljara_aludtunk=true;
      megteve=idozito.getHoltart();
      // ^^ bugfix by pts@fazekas.hu at Wed May 16 09:44:12 CEST 2001
      nem_rajzoltunk=nem_rajzoltunk_osszesen=0;
      // ^^^ bugfix by pts@fazekas.hu at Mon Apr 23 08:55:29 CEST 2001
      if (!idozito.isAlive()) idozito.start()// tényleg isAlive kell ide??
      mikor_inditottak=System.currentTimeMillis();
      rajzoltunk_osszesen=1;
    }

    public long getMegteve() { return megteve; }
    public long getEloirtPeriodus() { /*micros-ban*/ return 1000L*idozito.getInterval()}
    public long getSikerultPeriodus() { /*micros-ban*/
      return megteve==0?0:1000L*(System.currentTimeMillis()-mikor_inditottak)/megteve;
    }
    public long getLassuMuveletSzazalek() {
      return 100L*(rajzoltunk_osszesen)/(rajzoltunk_osszesen+nem_rajzoltunk_osszesen);
    }
    public long getGyorsMuvelet() { return rajzoltunk_osszesen; }
  } /// class Idozitett
} /// class Idozito