
import java.util.logging.Logger;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import java.io.PrintWriter;


class Settings
{
   private static final Logger LOGGER = Logger.getLogger(Settings.class.getName());

   static final String CUTOUT_PROPERTIES = "cutout.properties";


   public static class FITSPaths
   {
      private String FITSpath;
      private String FITScutpath;
      private String FITSRemoteUrlCutouts;
      private String surveysMetadataAbsPathname;

      public String surveys() {return FITSpath;};
      public String cutouts() {return FITScutpath;};
      public String cutoutsUrl() {return FITSRemoteUrlCutouts;};
      public String surveysMetadataAbsPathname() {return surveysMetadataAbsPathname;};

      public String toString()
      {
         return FITSpath + " " + FITScutpath + " " + FITSRemoteUrlCutouts + " " + surveysMetadataAbsPathname;
      }
   }


   public static class DBConn
   {
      private String uri;
      private String schema;
      private String user_name;
      private String password;

      public String toString()
      {
         return uri() + " [" + schema + "] " + user_name + " / " + password  + " ";
      }

      public boolean isDbUriEmpty()
      {
         return ((uri == null) || uri.trim().isEmpty());
      }

      public String uri() { return uri; }
      public String schema() { return schema; }
      public String userName() { return user_name; }
      public String password() { return password; }
   }


   public static class DefaultParamValues
   {
      String responseFormat;
      String skySystem;
      String specSystem;
      boolean showDuration;
   }


   public static class AmqpConn
   {
      private String hostName;
      private int    portNum;
      private String routingKey;

      public String hostName()   { return hostName; }
      public int    portNumber() { return portNum; }
      public String routingKey() { return routingKey; }

      public boolean isHostnameEmpty()
      {
         return ( (hostName == null) || hostName.trim().isEmpty() );
      }

      public String toString()
      {
         return hostName + " " + String.valueOf(portNum) + " " + routingKey;
      }
   }

   public FITSPaths  fitsPaths;
   public DBConn     dbConn;
   public AmqpConn   amqpConn;
   public DefaultParamValues defaults;


   // will not start without config-file
   // no reasonable code-defaults can be invented
   public static Settings getInstance()
   {
      LOGGER.config("Settings loading from: " + CUTOUT_PROPERTIES);
      try
      {
         InputStream ins =
            Settings.class.getClassLoader().getResourceAsStream(CUTOUT_PROPERTIES);

         if (ins != null)
         {
            Properties properties = new Properties();
            properties.load(ins);

            FITSPaths fitsPaths = loadFITSPaths(properties);
            DBConn    dbConn    = loadDBConn(properties);
            AmqpConn  amqpConn  = loadAmqpConn(properties);
            DefaultParamValues defaults = loadDefaults(properties);

            return new Settings(dbConn, amqpConn, fitsPaths, defaults);
         }
         else
         {
            throw new IllegalStateException(CUTOUT_PROPERTIES + " not found in classpath");
         }

      }
      catch(IOException ex)
      {
         throw new IllegalStateException("Error while loading " + CUTOUT_PROPERTIES + " file", ex);
      }
   }



   private Settings(DBConn dbConn, AmqpConn amqpConn,
         FITSPaths fitsPaths, DefaultParamValues defaults)
   {
      this.fitsPaths = fitsPaths;
      this.dbConn    = dbConn;
      this.amqpConn  = amqpConn;
      this.defaults  = defaults;
   }



   private static FITSPaths loadFITSPaths(Properties properties)
   {
      FITSPaths fitspaths = new FITSPaths();
      fitspaths.FITSpath             = properties.getProperty("fits_path_surveys", "/srv/surveys").strip();
      fitspaths.FITScutpath          = properties.getProperty("fits_path_cutouts", "/srv/cutouts").strip();
      fitspaths.FITSRemoteUrlCutouts = properties.getProperty("fits_url_cutouts",  "").strip();
      fitspaths.surveysMetadataAbsPathname = properties.getProperty("surveys_metadata_abs_pathname", "").strip();
      //fitspaths.surveysMetadataAbsPathname = properties.getProperty("surveys_metadata_abs_pathname", "/srv/surveys/survey_populate.csv").strip();
      return fitspaths;
   }

   private static DBConn loadDBConn(Properties properties)
   {
      DBConn dbconn = new Settings.DBConn();
      dbconn.uri       = properties.getProperty("db_uri", "").strip();
      dbconn.schema    = properties.getProperty("db_schema", "").strip();
      dbconn.user_name = properties.getProperty("db_user_name", "").strip();
      dbconn.password  = properties.getProperty("db_password", "").strip();
      return dbconn;
   }

   private static DefaultParamValues loadDefaults(Properties properties)
   {
      DefaultParamValues defaults = new DefaultParamValues();
      defaults.responseFormat = properties.getProperty("default_response_format", "application/fits").strip();
      defaults.skySystem      = properties.getProperty("default_sky_system", "ICRS").strip();
      defaults.specSystem     = properties.getProperty("default_spec_system", "WAVE_Barycentric").strip();
      defaults.showDuration   = "yes".equals(properties.getProperty("show_duration", "no").strip());
      return defaults;
   }

   private static AmqpConn loadAmqpConn(Properties properties)
   {
      AmqpConn amqpconn = new AmqpConn();
      amqpconn.hostName   = properties.getProperty("amqp_host_name", "").strip();
      String strPortNum   = properties.getProperty("amqp_port", "5672").strip();
      amqpconn.portNum    = Integer.parseInt(strPortNum);
      amqpconn.routingKey = properties.getProperty("amqp_routing_key", "").strip();
      return amqpconn;
   }

}

