package com.dm;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.MotionEvent;
import android.widget.LinearLayout; // f. dynamisches Hinzugeben gebraucht
import android.widget.Button;
import android.widget.TextView;
import android.widget.ScrollView;

import java.io.File;
import java.io.FileInputStream;
import java.util.Date;
import java.util.regex.*;

/*
   Zwischen onCreate und onDestroy ist die Akt. am Leben
   Zwischen onStart und onStop ist die Aktiv. sichtbar
   Zwischen onResume und onPause ist Akt. im Vordergrund
*/

public class Dateimanager extends Activity
{
   private final static String TAG = "DatM";
   private View zeilen[] = new View[1000];  // Elemente
   private String eintrag[] = new String[1000];// Titel
   private String wurzel; // wg. zurück
   private boolean modusDateianzeigen = false;  // Verzeichnis oder Dateinhalt
   private Pattern muster = null;  // Filtermuster
   ButtonKlick bk = null;  // Verarbeitungsinstanz

   @Override
   public void onCreate(Bundle savedInstanceState)
   {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.main);
      // aktiviere die Buttons der Hauptansicht
      bk = new ButtonKlick();  // für alle Buttons eine Verarbeitungsinstanz
      button_melden(R.id.Button01);
      button_melden(R.id.Button02);
      button_melden(R.id.Button03);
   }

   @Override
   public void onStart()
   {
      super.onStart(); 
      datei_verzeichnis("/"); 
   } 

   private void datei_verzeichnis(String verz)
   {
     Log.i(TAG, "datei_verzeichnis betreten " + verz);
     LinearLayout la = (LinearLayout) findViewById(R.id.Ll02);
     if (la == null) return;

     wurzel = verz;  // beim nach oben gehen benutzt
     File eing = new File(verz);
     if (!eing.exists()) { Log.i(TAG, "nicht gefunden"); return; }
     if (!eing.isDirectory()) { inhalt_ausgeben(eing); return; }
     String [] rueck = eing.list();

     // bisherige Einträge überschreiben
     int i; int angez = 0;
     for (i = 0; i < rueck.length; ++i)
     {
       String bez_neu = verz + "/" + rueck[i];
       // wenn Muster, dann nur auf Dateien anwenden
       if (muster != null && !(new File(bez_neu).isDirectory()))
       { 
         // ggf. Filtern
	 Matcher m = muster.matcher(rueck[i]);
	 if (!m.find()) { Log.i(TAG, "ignoriert: " + rueck[i]); continue; }
       }
       eintrag[angez] = bez_neu; TextView tneu;
       if (zeilen[angez] != null)
       {
         tneu = (TextView) zeilen[angez]; tneu.setVisibility(View.VISIBLE);
       }
       else
       {
         tneu = new TextView(this);
         touch_setzen(tneu);
         la.addView(tneu); zeilen[angez] = tneu; 
       }
       ++angez; 
       tneu.setText(attribute_holen(verz, rueck[i]));
     }
     // die übrigen unsichtbar machen
     for (i = angez; i < zeilen.length && zeilen[i] != null; ++i)
     {
	zeilen[i].setVisibility(View.INVISIBLE);
     }
     Log.i(TAG, "datei_verzeichnis verlassen");
   }

   // Gibt im zweiten Textview den Inhalt aus
   private void inhalt_ausgeben (File dat)
   {
     Log.i(TAG, "Inhaltsausgabe");
     if (!dat.exists() || !dat.isFile() || !dat.canRead() || zeilen[0] == null) 
     {
       Log.i(TAG, "Datei nicht anzeigbar");
       return;
     }
     // ab der zweiten Zeile unsichtbar machen
     modusDateianzeigen = true;
     for (int i = 1; i < zeilen.length && zeilen[i] != null; ++i)
     {
       zeilen[i].setVisibility(View.INVISIBLE);
     }
     // Inhalt in zweites TextView schreiben
     StringBuffer inhalt;
     try
     {
       FileInputStream fis = new FileInputStream(dat);
       inhalt = new StringBuffer((int) dat.length()); // Größe !!!
       byte puffer[] = new byte[1024]; char [] zeichen = new char[1024];
       do
       {
         int rueck = fis.read(puffer);     
	 if (rueck <= 0) break;  
	 // Alle nicht-lesbaren Zeichen durch x ersetzen; Probleme bei Unicode
	 for (int i = 0; i < rueck; ++i) zeichen[i] = 
	   (puffer[i] < 32 && puffer[i] != '\n') ? 'x' : (char) puffer[i];
	 inhalt = inhalt.append (zeichen, 0, rueck);
	 if (rueck < 1024) break;
       } while (true);
       fis.close();
     } catch (Exception ex) { inhalt = new StringBuffer("Fehler: " + ex.getMessage()); } // Fehler anzeigen
     ((TextView) zeilen[0]).setText(inhalt.toString());
  }

  // Setzt Listener für eine View-Komponente
  private void touch_setzen(TextView tneu)
  {
    tneu.setOnTouchListener(new View.OnTouchListener() {

    private int erstesY;  // Merker, um Wisch-Eregnisse zu erkennen

    public boolean onTouch(View v, MotionEvent e) {
    // Bei Berührung Verzeichnis aufmachen oder Datei anzeigen
    int aktion = e.getAction();
    if (aktion == MotionEvent.ACTION_DOWN)
    {
      erstesY = (int) e.getY();
      Log.i(TAG, "druecken");
      return true;
    }
    if (aktion == MotionEvent.ACTION_UP)
    {
      int zweitesY = (int) e.getY();
      Log.i(TAG, "loslassen");
      if (!modusDateianzeigen && zweitesY - erstesY >= 10)
      {
        // nach unten
	return false;
      }
      else if (!modusDateianzeigen && erstesY - zweitesY >= 10)
      {
        // nach oben
	return false;
      }

      // Sollte in der Scrollview ein Eintrag sein
      int j;
      for (j = 0; j < zeilen.length; ++j) if (zeilen[j] == null || zeilen[j] == v) break;
      if (j == zeilen.length || zeilen[j] == null) Log.i(TAG, "Eintrag nicht gefunden");
      else if (modusDateianzeigen) return false;// in Anzeigebereich
      else {
        datei_verzeichnis(eintrag[j]);  /* zu tun: Anzeige aktual */
      }
      return true;// Ereignis verarbeitet
    }  // end if ACTION_UP

    return false;// Ereignis nicht verarbeitet
    }});
  }

  // zu tun: += ist ungünstig, Datumsausgabe verkürzen
  // Bei string und +=  oft: GC freed x objects / y bytes --> StringBuffer
   private String attribute_holen(String pfad, String dat)
   {
     // Log.i(TAG, "attribute_holen betreten");
     StringBuffer meld = new StringBuffer(70);
     File eing = new File(pfad + "/" + dat);
     if (!eing.exists())
     {
       meld = meld.append(dat);
       meld = meld.append(" existiert nicht");
     }
     else
     {
       meld = meld.append(eing.isDirectory() ? "d " : "  ");
       meld = meld.append(dat);
       if (eing.canRead()) meld = meld.append(", l");
       if (eing.canWrite()) meld = meld.append(", s");
       if (eing.isHidden()) meld = meld.append(", v");
       // bei manchen Dateien wird die Dateilänge mit 0 zurückgegeben !?
       if (eing.isFile() && eing.length() != 0) meld = meld.append(", " + new Long(eing.length()).toString() +
       " Byte");
       long zeitst = eing.lastModified();
       if (zeitst > 0) 
       {
         String ausg = new Date(zeitst).toString();
         int bis = ausg.indexOf("GMT");  // Zeitzone rausnehmen
         if (bis >= 0) ausg = ausg.substring(0,bis) + ausg.substring(bis+10);
         meld = meld.append(", " + ausg);
       }
     } 

     // Log.i(TAG, "attribute_holen raus");
     return meld.toString();
   }

   // sucht im aktuellen Pfad nach Dateien dieses Musters
   private void muster_suchen(String muster)
   {
     String verz = wurzel;
   }

    // Versucht, einen Button mit dem Ereingnishandler zu verknuepfen
    // findViewById liefert null, wenn Element z.B. nicht sichtbar
    private void button_melden(int id)
    {
      Button b = (Button) findViewById(id);
      if (b != null) b.setOnClickListener(bk);
      else Log.w("TAG", "Button " + id + " nicht registriert");
    }
    
   
   // fuer die 3 Buttons, hier eine zentrale innere Klasse zur Ereignisverwaltung
  class ButtonKlick implements View.OnClickListener
  {
    public void onClick(View v)
    {
      if (! (v instanceof Button)) return;
      Button b = (Button) v;
      // werte den konkreten Knopf aus
      int bid = b.getId();
      if (bid == R.id.Button01)
      {
        // Geräte-Ansicht
	Log.i(TAG, "Suche gewählt");
        // zutun: Suche nach Dateien kommt noch
      }
      else if (bid == R.id.Button02)
      {
        // Filter an-/abstellen - Ein TextView für Eingabe des Musters freischalten,
	Log.i(TAG, "Filtern gewählt");
        if (muster == null) 
	{
          try
          {
	    muster = Pattern.compile("conf");  // Testwert f. Filter
          } catch (PatternSyntaxException ex)  { Log.e(TAG, ex.getMessage()); }
        }
	else muster = null;  // beende die Filterung
	datei_verzeichnis(wurzel);  // Anzeige akt.
      }
      else if (bid == R.id.Button03)
      {
        // nach oben, Anzeige beenden
        modusDateianzeigen = false;  // ggf. Inhaltsanzeige beenden
        if (! wurzel.equals("/"))
	{
          int bis = wurzel.lastIndexOf("/");
	  if (bis >= 0)
	  {
            Log.i(TAG, "gehe nach oben");
            datei_verzeichnis(bis > 0 ? wurzel.substring(0,bis) : "/"); 
          }
	}
   
      }
      // else weitere Buttons auswerten
    }
  } // Ende Klasse ButtonKlick
}
