package ca.blarg.gdx;

import ca.blarg.gdx.events.EventManager;
import ca.blarg.gdx.graphics.*;
import ca.blarg.gdx.states.StateManager;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.g3d.ModelBatch;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.utils.Disposable;
import com.badlogic.gdx.utils.TimeUtils;

public abstract class GameApp implements Disposable {
	public final EventManager eventManager;
	public final StateManager stateManager;
	public final ViewportContext viewportContext;
	public final ExtendedSpriteBatch spriteBatch;
	public final BillboardSpriteBatch billboardSpriteBatch;
	public final ModelBatch modelBatch;
	public final SolidColorTextureCache solidColorTextures;
	public final DebugGeometryRenderer debugGeometryRenderer;
	public final ShapeRenderer shapeRenderer;

	boolean logHeapMemUsage = false;
	long lastHeapMemLogTime = 0;

	public GameApp() {
		Gdx.app.debug("GameApp", "ctor");

		eventManager = new EventManager();
		stateManager = new StateManager(this, eventManager);
		viewportContext = new ViewportContext(true);
		spriteBatch = new ExtendedSpriteBatch();
		billboardSpriteBatch = new BillboardSpriteBatch();
		modelBatch = new ModelBatch();
		solidColorTextures = new SolidColorTextureCache();
		debugGeometryRenderer = new DebugGeometryRenderer();
		shapeRenderer = new ShapeRenderer();

		Services.register(eventManager);
		Services.register(stateManager);
		Services.register(viewportContext);
		Services.register(spriteBatch);
		Services.register(billboardSpriteBatch);
		Services.register(modelBatch);
		Services.register(solidColorTextures);
		Services.register(debugGeometryRenderer);
		Services.register(shapeRenderer);
	}

	protected void toggleHeapMemUsageLogging(boolean enable) {
		logHeapMemUsage = enable;
		if (enable)
			lastHeapMemLogTime = TimeUtils.millis();
	}

	public abstract void onCreate();

	public void onResize(int width, int height) {
		Gdx.app.debug("GameApp", String.format("onResize(%d, %d)", width, height));
		viewportContext.onResize(width, height);
		stateManager.onResize();
	}

	public void onRender(float interpolation) {
		viewportContext.onPreRender();
		spriteBatch.setProjectionMatrix(viewportContext.getOrthographicCamera().combined);
		spriteBatch.setPixelScale(viewportContext.pixelScaler.getScale());

		stateManager.onRender(interpolation);

		viewportContext.onPostRender();
	}

	public void onUpdateGameState(float delta) {
		eventManager.onUpdate(delta);
		stateManager.onUpdateGameState(delta);
		if (stateManager.isEmpty()) {
			Gdx.app.debug("GameApp", "No states running. Quitting.");
			Gdx.app.exit();
			return;
		}

		if (logHeapMemUsage) {
			long currentTime = TimeUtils.millis();
			if (currentTime - lastHeapMemLogTime > 1000) {
				lastHeapMemLogTime = currentTime;
				Gdx.app.debug("GameApp", String.format("Heap memory usage: %d", Gdx.app.getJavaHeap()));
			}
		}
	}

	public void onUpdateFrame(float delta) {
		viewportContext.onUpdateFrame(delta);
		stateManager.onUpdateFrame(delta);
	}

	public void onPause() {
		Gdx.app.debug("GameApp", "onPause");
		stateManager.onAppPause();
		viewportContext.onPause();
		solidColorTextures.onPause();
	}

	public void onResume() {
		Gdx.app.debug("GameApp", "onResume");
		viewportContext.onResume();
		solidColorTextures.onResume();
		stateManager.onAppResume();
	}

	@Override
	public void dispose() {
		Gdx.app.debug("GameApp", "dispose");
		stateManager.dispose();
		solidColorTextures.dispose();
		modelBatch.dispose();
		billboardSpriteBatch.dispose();
		spriteBatch.dispose();
	}
}

@@ -113,56 +113,287 @@
 gdx.
-states.StateManager;%0Aimport com.badlogic.gdx.Gdx
+graphics.atlas.TextureAtlas;%0Aimport ca.blarg.gdx.graphics.atlas.json.TextureAtlasLoader;%0Aimport ca.blarg.gdx.states.StateManager;%0Aimport com.badlogic.gdx.Gdx;%0Aimport com.badlogic.gdx.assets.AssetManager;%0Aimport com.badlogic.gdx.assets.loaders.resolvers.InternalFileHandleResolver
 ;%0Aim
@@ -633,16 +633,57 @@
 sable %7B%0A
+%09public final AssetManager assetManager;%0A
 %09public 
@@ -1226,16 +1226,53 @@
 tor%22);%0A%0A
+%09%09assetManager = new AssetManager();%0A
 %09%09eventM
@@ -1679,16 +1679,156 @@
 rer();%0A%0A
+%09%09assetManager.setLoader(TextureAtlas.class, new TextureAtlasLoader(new InternalFileHandleResolver()));%0A%0A%09%09Services.register(assetManager);%0A
 %09%09Servic

add AssetManager instance to GameApp. initialize with our custom loaders