package org.bucksch.zeipis.all;
import java.sql.*;
import java.io.*;
import java.util.*;

public class DB
{
  public DB()
    throws SQLException, Misconfiguration
  {
    try {
      Class.forName("com.mysql.jdbc.Driver");
    } catch (ClassNotFoundException e) {
      throw new SQLException("Please install MySQL Connector/J");
    }
    me = this;
    readConfig();
  }

  public Connection database()
    throws SQLException
  {
    try {
      //if (myConnection != null && myConnection.isValid(100)) TODO Java 1.6 only?
      if (myConnection != null)
        return myConnection;
    } catch (Exception e) {} // fall to below code

    assert (myDBURL != null);
    myConnection = DriverManager.getConnection(myDBURL);
    startKeepAlive();
    return myConnection;
  }
  public void startKeepAlive()
  {
    try {
      if (myKeepAliveTimer != null)
        myKeepAliveTimer.cancel();
      myKeepAliveTimer = new Timer("DB keep alive ping", false);
      myKeepAliveTimer.schedule(new TimerTask() {
        public void run() {
          try {
            //if ( ! myConnection.isValid(3000))
            //  throw new SQLException();
            myConnection.createStatement().execute("SELECT deviceid FROM device");
          } catch (Exception e) {
            Util.error("Database connection died", e);
          }
        }
      }, 0, 60 * 60 * 1000); // every hour
    } catch (Exception e) { Util.error(e); }
  }

  protected Map<String, String> readConfig()
    throws Misconfiguration
  {
    Map<String, String> vars;
    String filename;
    try {
      filename = "/etc/zeipis/start.conf";
      vars = readInitFile(filename);
    } catch (FileNotFoundException e) {
      try {
        filename = System.getProperty("user.home") + "/.zeipis/start.conf";
        vars = readInitFile(filename);
      } catch (FileNotFoundException e2) {
        throw new Misconfiguration("Please create the zeipis start.conf, and - if not already done - install Zeipis server. See the documentation for how to do that.", e2);
      }
    }

    if (vars.isEmpty() ||
        ! vars.containsKey("dbhostname") ||
        ! vars.containsKey("dbname") ||
        ! vars.containsKey("dbusername") ||
        ! vars.containsKey("dbpassword") ||
        ! vars.containsKey("coreserverhostname"))
      throw new Misconfiguration("start.conf file " + filename + " does not contain the necessary information. Please see the documentation and correct the file");
  
    String dbname = vars.get("dbname");
    String dbhostname = vars.get("dbhostname");
    String username = vars.get("dbusername");
    String password = vars.get("dbpassword");
    myCoreServerHostname = vars.get("coreserverhostname");

    myDBURL = "jdbc:mysql://" + dbhostname + "/" + dbname + "?user=" + username + "&password=" + password;
    
    return vars;
  }

  static public Map<String, String> readInitFile(String filename)
    throws FileNotFoundException, Misconfiguration
  {
    Map<String, String> vars = Util.newMap();
    InputStream stream = new FileInputStream(new File(filename));
    try {
      BufferedReader br = new BufferedReader(new InputStreamReader(stream));
      String input;
      while ((input = br.readLine()) != null)
      {
        try {
          if (input.trim().length() == 0 ||
              input.charAt(0) == '#')
            continue;
          String[] keyAndValue = input.split("=");
          if (keyAndValue.length < 2)
            throw new Exception("Malformed line in " + filename + ": " + input);
          String key = keyAndValue[0].trim().toLowerCase(Locale.ENGLISH);
          String value = keyAndValue[1].trim();
          vars.put(key, value);
        } catch (Exception e) { Util.error(e); }
      }
    } catch (Exception e) {
      throw new Misconfiguration("Can't read " + filename, e);
    }
    return vars;
  }

  public static DB me = null;
  protected static Connection myConnection;
  protected Timer myKeepAliveTimer = null;
  protected String myDBURL = null;
  public String myCoreServerHostname = null; // only for CoreServer
}
