package org.bucksch.zeipis.store;
import org.bucksch.zeipis.all.*;
import org.bucksch.zeipis.recorder.ScheduledRecording;
import java.io.*;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.SimpleDateFormat;

public class LocalStore implements Store
{
  public LocalStore(String storeName)
    throws Misconfiguration, SQLException
  {
    myStoreName = storeName;

    File directory = readDatabase(storeName);

    if (!directory.exists())
      throw new Misconfiguration("storage directory " + directory.getPath() + " does not exist");
    if (!directory.isDirectory())
      throw new Misconfiguration("storage directory " + directory.getPath() + " is not a directory");
    if (!directory.canRead())
      throw new Misconfiguration("storage directory " + directory.getPath() + " is not readable");
    myDirectory = directory;
  }
  protected File readDatabase(String storeName)
    throws Misconfiguration, SQLException
  {
    PreparedStatement findStore = DB.me.database().prepareStatement("SELECT * FROM store WHERE storename = ?");
    findStore.setString(1, storeName);
    ResultSet rs = findStore.executeQuery();
    if (!rs.first())
      throw new Misconfiguration("No such storename");
    if ( ! Util.isThisHost(rs.getString("host")))
      throw new Misconfiguration("Not a store on this host");
    String dirname = rs.getString("directoryname");
    return new File(dirname);
  }

  public Source getFile(StoredRecording recording)
    throws FileNotFoundException
  {
    return new LocalfileSource(getAbsoluteFile(recording.relFilename()));
  }
  public Target saveFile(ScheduledRecording recording)
    throws FileNotFoundException
  {
    String relFilename = generateFilename(recording);
    return new LocalfileTarget(getAbsoluteFile(relFilename), relFilename);
  }
  public Source getFile(String relFilename)
    throws FileNotFoundException
  {
    return new LocalfileSource(getAbsoluteFile(relFilename));
  }
  public Target saveFile(String relFilename)
    throws FileNotFoundException
  {
    return new LocalfileTarget(getAbsoluteFile(relFilename), relFilename);
  }
  protected File getAbsoluteFile(String filename)
  {
    // !XXX Security: Ensure that filename is really relative.
    return new File(myDirectory, filename);
  }
  static protected String generateFilename(ScheduledRecording recording)
  {
    // XXX using station will give collisions if same film recorded on 2 channels
    return (new SimpleDateFormat("yyyyMMdd-HHmm").format(recording.starttime())) + "-" + recording.stationID() + ".mpg";
  }
  public long freeSpace()
  {
    try {
      // Java 1.6
      return myDirectory.getFreeSpace(); // TODO get mount root
    } catch (NoSuchMethodError e) {
      // Java 1.5
      // throw new RuntimeException("TODO parse /proc/diskstats");
      return 10000000000000L; // !XXX free space
    }
  }

  public String host() { return Util.thisHostname(); }
  public boolean isLocal() { return true; }
  public String storeName() { return myStoreName; }
  public String toString() { return myStoreName + " (local) " + myDirectory; }

  protected File myDirectory;
  protected String myStoreName;
}
