package org.bucksch.zeipis.core;
import org.bucksch.zeipis.all.*;
import org.bucksch.zeipis.recorder.*;
import org.bucksch.zeipis.store.*;
import org.bucksch.httpserver.HTTPDirectoryHandler;
import org.bucksch.httpserver.HTTPServer;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.sql.SQLException;

public class CoreServer
{
  public static void main(String[] args)
  {
    new CoreServer();
  }
  static public CoreServer me;
  protected CoreServer()
  {
    me = this;
    try {
      startup();
      mainLoop();

    // Global catches
    } catch (SQLException e) {
      System.out.println("SQL exception: " + e.getMessage());
      System.out.println("SQL state: " + e.getSQLState());
      System.out.println("MySQL error: " + e.getErrorCode());
      e.printStackTrace();
    } catch (Exception e) {
      System.out.println("Unhandled Exception: " + e.getMessage());
      e.printStackTrace();
    }
  }
  protected void mainLoop()
    throws Exception
  {
    myDispatchingServer.loop();
  }
  protected void startup()
    throws Exception
  {
    new DB();
    new CoreData();
    myCoreServerHostname = DB.me.myCoreServerHostname; // DB() reads the start.conf file
    Util.debug("Hostname " + Util.thisHostname() + ", port " + myPort);

    myDispatchingServer = new HTTPServer(myPort);

    myFileServer = new HTTPDirectoryHandler("zeipis/", new File("httpstatic/"));

    // Store server
    boolean haveLocalStore = false;
    for (Store store : CoreData.me.myStores.values())
      if (store.isLocal())
        haveLocalStore = true;
    if (haveLocalStore)
      new LocalRecordingsProvider();

    // Core server
    if (Util.isThisHost(myCoreServerHostname))
    {
      Util.debug("I'm the core server");
      new RecordingsListingProvider();
      new RecordingsManagementProvider();
      myScheduler = new Scheduler();
      myScheduler.schedule();
    }
    else
    {
      Util.debug("I'm a secondary server");

      // TV card server
      boolean haveLocalDevice = false;
      for (Device card : CoreData.me.myCards.values())
        if (card.isLocal())
          haveLocalDevice = true;
      if (haveLocalDevice)
        new TVCardProvider();
    }
  }


  // Getter/setter

  public Scheduler scheduler()
  {
    return myScheduler;
  }
  public HTTPServer dispatchingServer()
  {
    return myDispatchingServer;
  }
  public String coreServerName()
  {
    return myCoreServerHostname; // TODO port number
  }
  public URL baseURLForHost(String host)
  {
    try {
      return new URL("http://" + host + ":" + myPort);
    } catch (MalformedURLException e) { throw new RuntimeException(e); }
  }


  // Data
  protected Scheduler myScheduler;
  protected HTTPServer myDispatchingServer;
  protected HTTPDirectoryHandler myFileServer;

  // Config
  static protected int myPort = 4962; // TODO configurable
  protected String myCoreServerHostname = null;
}
