package com.dubiousoft.sakana;

import java.util.Timer;
import java.util.TimerTask;

import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLContext;
import javax.microedition.khronos.egl.EGLDisplay;

import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.os.Handler;
import android.app.Activity;
import android.content.Intent;
import android.content.res.AssetManager;
import android.graphics.Point;
import android.view.Display;
import android.view.Menu;
import android.view.Window;
import android.view.WindowManager;

public class GameScreenActivity extends Activity 
	implements GameScreenThread.Listener
{
	public final static String SCENE_MESSAGE = "com.dubiousoft.sakana.SCENE_MESSAGE";
	
	private NativeSakana m_nativeLayer;
	private GameScreenView m_view;
	private GameScreenThread m_thread = null;
	private GLSurfaceView m_glSurfaceView = null;
	private Handler m_handler = null;
	private Timer m_timer = null;
	private SceneManager m_sceneManager = null;
	private int m_sceneIndex = 0;
	private String m_sceneName;
	private int m_starLow=0;
	private int m_starMed=0;
	private int m_starHigh=0;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, 
							 WindowManager.LayoutParams.FLAG_FULLSCREEN);
		
		Utils.LOG( "GameScreenActivity started" );
		Intent intent = getIntent();
		if (intent != null) {
			Utils.LOG("Intent exists" );
			m_sceneIndex = intent.getIntExtra( SCENE_MESSAGE, 0 );
		}
		
		Display display = getWindowManager().getDefaultDisplay();
		Point size = new Point();
		display.getSize( size );
		AssetManager mgr = getAssets();
		
		m_sceneManager = new SceneManager( mgr );
		if (m_sceneIndex >= m_sceneManager.getSize()) {
			m_sceneIndex = 0;
		}
		SceneManager.SceneNode sceneNode = m_sceneManager.getNode( m_sceneIndex );
		m_sceneName = sceneNode.name;
		m_starLow = sceneNode.scores.Min;
		m_starMed = sceneNode.scores.Avg;
		m_starHigh = sceneNode.scores.High;
		m_nativeLayer = new NativeSakana( mgr, size, m_sceneManager.getNode( m_sceneIndex ).path );

		m_view = new GameScreenView( this, m_nativeLayer );
		setContentView( m_view );

		m_glSurfaceView = new GLSurfaceView( this );
		m_glSurfaceView.setEGLContextClientVersion(1);		
		EGL10 egl = (EGL10)EGLContext.getEGL();
		EGLDisplay eglDisplay = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
		EnumerateConfigs( egl, eglDisplay );
		m_glSurfaceView.setEGLConfigChooser( 8, 8, 8, 8, 16, 8 );
		m_glSurfaceView.setRenderer(new GameScreenRenderer( m_nativeLayer ));
		
		m_view.addView( m_glSurfaceView, 0 );
		m_handler = new Handler();
	}
	
	private void startGameThread() {
		m_thread = new GameScreenThread( this );
		m_thread.start();
	}
	
	private void stopGameThread() {
		if (m_thread != null) {
			try {
				m_thread.stopRun();
				m_thread.join();
				m_thread = null;
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
	
	private void startUiUpdateTimer() {
		m_timer = new Timer();
		m_timer.scheduleAtFixedRate( new TimerTask() {
			@Override
			public void run() {
				m_handler.post( new Runnable() {
					@Override
					public void run() {
						onUiUpdateEvent();
					}} );
			}}, 16, 16 );
	}
	
	private void stopUiUpdateTimer() {
		if (m_timer != null) {
			m_timer.cancel();
			m_timer = null;
		}
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.game, menu);
		return true;
	}
		     
	@Override
	protected void onPause() {
	    super.onPause();
	 
	    Utils.LOG( "onPause" );
	    if (m_glSurfaceView != null) {
	    	m_glSurfaceView.onPause();
	    }
	    stopGameThread();
	    stopUiUpdateTimer();
	}
	 
	@Override
	protected void onResume() {
	    super.onResume();
	 
	    Utils.LOG( "onResume" );
	    if (m_glSurfaceView != null) {
	    	m_glSurfaceView.onResume();
	    }
	    startGameThread();
	    startUiUpdateTimer();
	}

    @Override
    public void onBackPressed() {
        Intent intent = new Intent( this, SceneSelectionActivity.class );
        intent.addFlags( Intent.FLAG_ACTIVITY_CLEAR_TOP );
        startActivity( intent );
    }

	@Override
	public void onThreadEvent( long milliSeconds ) {
		// This is run from the GameScreenThread
		// You can't do any UI stuff.
		// UI is refreshed through the GameScreenRenderer
		m_nativeLayer.Physics( (float) (milliSeconds/1000.0) );
	}
	
	private void onUiUpdateEvent() {
		if (m_nativeLayer.SceneIsFinished()) {
			Intent intent = new Intent( this, SceneResultsActivity.class );
			intent.putExtra( SceneResultsActivity.SCORE_MESSAGE, m_nativeLayer.Score() );
			intent.putExtra( SceneResultsActivity.SCENE_INDEX_MESSAGE, m_sceneIndex );
			intent.putExtra( SceneResultsActivity.SCENE_NAME_MESSAGE, m_sceneName );
			intent.putExtra( SceneResultsActivity.STAR_LOW_MESSAGE, m_starLow );
			intent.putExtra( SceneResultsActivity.STAR_MED_MESSAGE, m_starMed );
			intent.putExtra( SceneResultsActivity.STAR_HIGH_MESSAGE, m_starHigh );
			startActivity( intent );
			return;
		}
		// This is run from the UI thread.
		// You can do refresh stuff in here.
		m_view.onUiUpdate();
	}

	private void EnumerateConfigs( EGL10 egl, EGLDisplay Display )
	{
		int[] 		NumConfigs = new int[100];
		EGLConfig[] Config = new EGLConfig[100];
		
		if (egl.eglGetConfigs( Display, Config, 100, NumConfigs ) != true ) {
			return;
		}
		for (int i=0; i<100; ++i) {
			if (Config[i] != null) {
				int[] value = new int[1];
				
				Utils.LOG( String.format("conf[%d] = %s", i, Config[i].toString() ) );
				
				egl.eglGetConfigAttrib(Display, Config[i], EGL10.EGL_RED_SIZE, value);
				Utils.LOG( String.format("EGL_RED_SIZE  = %d", value[0] ) );
				
				egl.eglGetConfigAttrib(Display, Config[i], EGL10.EGL_BLUE_SIZE, value);
				Utils.LOG( String.format("EGL_BLUE_SIZE  = %d", value[0] ) );

				egl.eglGetConfigAttrib(Display, Config[i], EGL10.EGL_GREEN_SIZE, value);
				Utils.LOG( String.format("EGL_GREEN_SIZE  = %d", value[0] ) );

				egl.eglGetConfigAttrib(Display, Config[i], EGL10.EGL_ALPHA_SIZE, value);
				Utils.LOG( String.format("EGL_ALPHA_SIZE  = %d", value[0] ) );
				
				egl.eglGetConfigAttrib(Display, Config[i], EGL10.EGL_DEPTH_SIZE, value);
				Utils.LOG( String.format("EGL_DEPTH_SIZE  = %d", value[0] ) );
				
				egl.eglGetConfigAttrib(Display, Config[i], EGL10.EGL_STENCIL_SIZE, value);
				Utils.LOG( String.format("EGL_STENCIL_SIZE  = %d", value[0] ) );
			}
		}
	}	
}
