/*
 * Copyright 2012 Ross Bamford
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License. 
 */
package com.roscopeco.ormdroid;

import android.app.Application;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.util.Log;

/**
 * <p>Provides static-initialization for the ORMDroid framework.
 * The {@link #initialize(Context)} method must be called with
 * a valid {@link Context} prior to using any framework methods
 * that reference the default database.</p>
 * 
 * <p>Note that this class extends {@link android.app.Application},
 * allowing you to set it as the Application class in your manifest
 * to have this initialization handled automatically.</p>
 */
public class ORMDroidApplication extends Application {
  private static ORMDroidApplication singleton;  
  private Context mContext;
  private String mDBName;

  private static void initInstance(ORMDroidApplication app, Context ctx) {
    app.attachBaseContext(app.mContext = ctx.getApplicationContext());
  }
  
  public static boolean isInitialized() {
    return (singleton != null);
  }
  
  /**
   * <p>Intialize the ORMDroid framework. This <strong>must</strong> be called before
   * using any of the methods that use the default database.</p>
   * 
   * <p>If your application doesn't use the default database (e.g. you pass in your
   * own {@link SQLiteDatabase} handle to the {@link Query#execute(SQLiteDatabase)} and
   * {@link Entity#save(SQLiteDatabase)} methods) the you don't <i>technically</i>
   * need to call this, but it doesn't hurt.</p>
   * 
   * <p>This method may be called multiple times - subsequent calls are simply 
   * ignored.</p>
   * 
   * @param ctx A {@link Context} within the application to initialize.
   */
  public static void initialize(Context ctx) {
    if (!isInitialized()) {
      initInstance(singleton = new ORMDroidApplication(), ctx);
    }
  }

  /**
   * Obtain the singleton instance of this class.
   * 
   * @return the singleton instance.
   */
  public static ORMDroidApplication getSingleton() {
    if (!isInitialized()) {
      Log.e("ORMDroidApplication", "ORMDroid is not initialized");
      throw new ORMDroidException("ORMDroid is not initialized - You must call ORMDroidApplication.initialize");
    }

    return singleton;
  }
  
  /**
   * Obtain the default database used by the framework. This
   * is a convenience that calls {@link #getDatabase()} on the
   * singleton instance.
   * 
   * @return the default database.
   */
  public static SQLiteDatabase getDefaultDatabase() {
    return getSingleton().getDatabase();    
  }
  
  @Override
  public void onCreate() {
    if (singleton != null) {
      throw new IllegalStateException("ORMDroidApplication already initialized!");
    }
    singleton = this;
    mContext = getApplicationContext();
    //initInstance(this, getApplicationContext());
  }
  
  private void initDatabaseConfig() {
    try {
      ApplicationInfo ai = mContext.getPackageManager().getApplicationInfo(mContext.getPackageName(), PackageManager.GET_META_DATA);
      mDBName = ai.metaData.get("ormdroid.database.name").toString();
    } catch (Exception e) {
      throw new ORMDroidException("ORMDroid database configuration not found; Did you set properties in your app manifest?", e);
    }
  }
  
  /**
   * Get the database name used by the framework in this application.
   * 
   * @return The database name.
   */
  public String getDatabaseName() {
    if (mDBName == null) {
      initDatabaseConfig();
    }
    return mDBName;
  }
  
  /**
   * Get the database used by the framework in this application.
   * 
   * @return The database.
   */
  public SQLiteDatabase getDatabase() {
  	try {
      return SQLiteDatabase.openDatabase(getDatabaseName(), null, SQLiteDatabase.OPEN_READWRITE);  		
  	} catch (SQLiteException e) {
  		// Couldn't open the database. It may never have existed, or it may have been
  		// deleted while the app was running. If this is the case, entity mappings may still
  		// be hanging around from that run, with their mSchemaCreated flag set to true. Since
  		// this information is now stale, let's flush it (See issue #17).
  		Entity.flushSchemaCreationCache();
  		
  		return openOrCreateDatabase(getDatabaseName(), 0, null);
  	}
  }  
}

@@ -1623,70 +1623,132 @@
 app.
-attachBaseContext(app.mContext = ctx.getApplicationContext());
+mContext = ctx.getApplicationContext();%0D%0A%09%09if (app.getBaseContext() == null) %7B%0D%0A%09%09%09app.attachBaseContext(app.mContext);%0D%0A%09%09%7D
 %0D%0A  
@@ -3592,51 +3592,8 @@
     
-mContext = getApplicationContext();%0D%0A    //
 init
@@ -4528,32 +4528,57 @@
 se.openDatabase(
+mContext.getDatabasePath(
 getDatabaseName(
@@ -4578,16 +4578,27 @@
 seName()
+).getPath()
 , null, 
@@ -4628,20 +4628,16 @@
 DWRITE);
-  %09%09
 %0D%0A  %09%7D c

Fix [#28]