package daruma.global_switch;

import daruma.util.PropertyReader;
import daruma.util.FatalException;

import daruma.auth.PermissionType;

public class ImplementationSwitches
{
    //
    // geometry conversion
    //
    private static final String ENABLE_GEOMETRY_CONVERSION_PROPERTY
				= "daruma.geometry.enable_conversion";
    private static final boolean ENABLE_GEOMETRY_CONVERSION_DEFAULT
				 = true;
    private boolean enableGeometryConversion = ENABLE_GEOMETRY_CONVERSION_DEFAULT;


    private static final String ALLOW_CONVERSION_TO_LOWER_DIMENSION_PROPERTY
		= "daruma.geometry.allow_conversion_to_lower_dimension";
    private static final String ALLOW_CONVERSION_TO_UPPER_DIMENSION_PROPERTY
		= "daruma.geometry.allow_conversion_to_upper_dimension";
    private static final boolean ALLOW_CONVERSION_TO_LOWER_DIMENSION_DEFAULT
				 = true;
    private static final boolean ALLOW_CONVERSION_TO_UPPER_DIMENSION_DEFAULT
				 = true;
    private boolean allowConversionToLowerDimension = ALLOW_CONVERSION_TO_LOWER_DIMENSION_DEFAULT;
    private boolean allowConversionToUpperDimension = ALLOW_CONVERSION_TO_UPPER_DIMENSION_DEFAULT;

    //
    // db index
    //
    private static final String CREATE_GEOMETRY_INDEX_PROPERTY
		= "daruma.geometry.create_geometry_index";
    private static final boolean CREATE_GEOMETRY_INDEX_DEFAULT = false;
    private boolean createGeometryIndex = CREATE_GEOMETRY_INDEX_DEFAULT;



    //
    // backend database type
    //
    public enum BackendDBType { PostGIS, MySQL };
    private String BACKEND_DB_TYPE_PROPERTY = "daruma.db.backend";
    private static final String BACKEND_DB_TYPE_DEFAULT = "MySQL";
    private BackendDBType backendDBType = BackendDBType.MySQL;

    //
    // MySQL host & port
    //
    private String MYSQL_HOST_PROPERTY = "daruma.mysql.host";
    private String MYSQL_PORT_PROPERTY = "daruma.mysql.port";
    private static final String MYSQL_HOST_DEFAULT = "localhost";
    private static final int MYSQL_PORT_DEFAULT = 3306;
    private static String mysqlHost = MYSQL_HOST_DEFAULT;
    private static int mysqlPort = MYSQL_PORT_DEFAULT;


    //
    // auth
    //
    private static final String AUTH_DEFAULT_RULE_PROPERTY
					= "daruma.auth.default_rule";
    private static final PermissionType AUTH_DEFAULT_RULE_DEFAULT
					= PermissionType.Deny;
    private static PermissionType authDefaultRule = AUTH_DEFAULT_RULE_DEFAULT;


    //
    // net
    //
    private static final String NET_TIMEOUT_MSEC_PROPERTY
					= "daruma.net.timeout_msec";
    private static final int NET_TIMEOUT_MSEC_DEFAULT = 300 * 1000;
    private static int netTimeoutMSec = NET_TIMEOUT_MSEC_DEFAULT;


    //
    // debug
    //
    private static final String DO_FULL_GC_PROPERTY = "daruma.debug.do_full_gc";
    private static final boolean DO_FULL_GC_DEFAULT = false;
    private static boolean doFullGC = DO_FULL_GC_DEFAULT;


    public ImplementationSwitches() throws FatalException
    {
	//
	// geometry
	//
	this.enableGeometryConversion
	    = PropertyReader.getProperty
	      ( ENABLE_GEOMETRY_CONVERSION_PROPERTY,
		ENABLE_GEOMETRY_CONVERSION_DEFAULT );

	this.allowConversionToLowerDimension
	    = PropertyReader.getProperty
	      ( ALLOW_CONVERSION_TO_LOWER_DIMENSION_PROPERTY,
		ALLOW_CONVERSION_TO_LOWER_DIMENSION_DEFAULT );

	this.allowConversionToUpperDimension
	    = PropertyReader.getProperty
	      ( ALLOW_CONVERSION_TO_UPPER_DIMENSION_PROPERTY,
		ALLOW_CONVERSION_TO_UPPER_DIMENSION_DEFAULT );


	//
	// db index
	//
	this.createGeometryIndex
	    = PropertyReader.getProperty
	      ( CREATE_GEOMETRY_INDEX_PROPERTY,
		CREATE_GEOMETRY_INDEX_DEFAULT );


	//
	// backend database type
	//
	String backendDBTypeString 
	    = PropertyReader.getProperty
	      ( BACKEND_DB_TYPE_PROPERTY,
		BACKEND_DB_TYPE_DEFAULT );

	if ( backendDBTypeString.equals( "PostGIS" ) )
	{
	    this.backendDBType = BackendDBType.PostGIS;
	}
	else if ( backendDBTypeString.equals( "MySQL" ) )
	{
	    this.backendDBType = BackendDBType.MySQL;
	}
	else
	{
	    throw new FatalException
		( "invalid property value of ["
		  + BACKEND_DB_TYPE_PROPERTY + "],"
		  + " value = [" + this.backendDBType + "],"
		  + " expected was [PostGIS] or [MySQL]." );
	}

	this.mysqlHost = PropertyReader.getProperty( MYSQL_HOST_PROPERTY,
						     MYSQL_HOST_DEFAULT );

	this.mysqlPort = PropertyReader.getProperty( MYSQL_PORT_PROPERTY,
						     MYSQL_PORT_DEFAULT );

	//
	// auth
	//
	{
	    final String defaultRuleString
		= PropertyReader.getProperty( AUTH_DEFAULT_RULE_PROPERTY );

	    if ( defaultRuleString == null )
	    {
		this.authDefaultRule = AUTH_DEFAULT_RULE_DEFAULT;
	    }
	    else if ( defaultRuleString.equals( "allow" ) )
	    {
		this.authDefaultRule = PermissionType.Allow;
	    }
	    else if ( defaultRuleString.equals( "deny" ) )
	    {
		this.authDefaultRule = PermissionType.Deny;
	    }
	    else
	    {
		throw new FatalException
		    ( "invalid property value of ["
		      + AUTH_DEFAULT_RULE_PROPERTY + "],"
		      + " value = [" + defaultRuleString + "],"
		      + " expected was [allow] or [deny]." );
	    }
	}


	//
	// net
	//
	this.netTimeoutMSec
	    = PropertyReader.getProperty
	      ( NET_TIMEOUT_MSEC_PROPERTY,
		NET_TIMEOUT_MSEC_DEFAULT );


	//
	// debug
	//
	this.doFullGC = PropertyReader.getProperty( DO_FULL_GC_PROPERTY,
						    DO_FULL_GC_DEFAULT );
    }


    //
    // geometry
    //
    public boolean getEnableGeometryConversion()
    {
	return enableGeometryConversion;
    }

    public boolean getAllowConversionToLowerDimension()
    {
	return allowConversionToLowerDimension;
    }

    public boolean getAllowConversionToUpperDimension()
    {
	return allowConversionToUpperDimension;
    }


    //
    // db index
    //
    public boolean getCreateGeometryIndex()
    {
	return createGeometryIndex;
    }


    //
    // backend database type
    //
    public BackendDBType getBackendDBType()
    {
	return backendDBType;
    }

    public boolean isPostGISBackend()
    {
	return backendDBType == BackendDBType.PostGIS;
    }

    public boolean isMySQLBackend()
    {
	return backendDBType == BackendDBType.MySQL;
    }

    public String getMySQLHost()
    {
	return mysqlHost;
    }

    public int getMySQLPort()
    {
	return mysqlPort;
    }


    //
    // auth
    //
    public PermissionType getAuthDefaultRule()
    {
	return authDefaultRule;
    }

    //
    // net
    //
    public int getNetTimeoutMSec()
    {
	return netTimeoutMSec;
    }

    //
    // debug
    //
    public boolean getDoFullGC()
    {
	return doFullGC;
    }



    //
    // singleton
    //
    private static ImplementationSwitches obj = null;

    public static void createInstance() throws FatalException
    {
	if ( obj == null )
	{
	    obj = new ImplementationSwitches();
	}
    }

    public static ImplementationSwitches instance()
    {
	return obj;
    }
}
