package com.darkdimension.ritle_run;

import com.darkdimension.ritle_run.Menu.Action;

import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.media.AudioManager;
import android.media.SoundPool;
import android.net.Uri;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class GameSurface extends SurfaceView
        implements SurfaceHolder.Callback, Runnable
{
    //Thread
    private Thread gThread;
    private boolean running = false;

    //Surface
    public static int width, height;
    public static float density;
    public static boolean isPhone;

    //Menus
    private Menu menu = null;

    //Font
    public static Paint font = new Paint();

    //Sounds
    private static SoundPool soundPool;
    private static int sound[];
	public static boolean bSound;

	//Save-load
	SharedPreferences sharedPref;

    public GameSurface(Context context)
    {
        super(context);

        //Callback to Surface calls
        getHolder().addCallback(this);

        //Focus
        setFocusable(true);
    }

    public boolean onTouchEvent(MotionEvent event)
    {
        //Touch Current Menu
        if (menu != null)
            if (event.getAction() == MotionEvent.ACTION_DOWN
            &&  !menu.isAnimating())
                return menu.touch((int)event.getX(), (int)event.getY());

        //Return super touch
        return super.onTouchEvent(event);
    }

    public void update()
    {
        //Update Current Menu and act accordingly
        switch (menu.update())
        {
            //Menus
            case TO_MAIN_MENU:
				if (menu instanceof MenuGame)
					menu = new MenuMain(getResources(), ((MenuGame)menu).hardReset);
				else
                	menu = new MenuMain(getResources(), false);
                break;
            case TO_GAME:
				if (menu instanceof MenuGame)
                	menu = new MenuGame(getResources(), getHighScore(), ((MenuGame)menu).hardReset);
				else
					menu = new MenuGame(getResources(), getHighScore(), false);
                break;
            case TO_EXTRA:
                menu = new MenuExtra(getResources());
                break;

            //Exit Game
            case EXIT_GAME:
                ExitGame();
                break;

            //Social Sites
            case TO_PLAY_STORE:
                Intent playIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://market.android.com/search?q=pub:Dark Dimension"));
                getContext().startActivity(playIntent);
                break;
            case TO_FACEBOOK:
                Intent facebookIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.facebook.com/DarkDimensionGames"));
                getContext().startActivity(facebookIntent);
                break;
            case TO_TUMBLR:
                Intent tumblrIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://t0mkun.tumblr.com"));
                getContext().startActivity(tumblrIntent);
                break;
            case TO_TWITTER:
                Intent twitterIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://twitter.com/DDimensionGames"));
                getContext().startActivity(twitterIntent);
                break;

            //Ads
            case SHOW_AD:
                //Set new high score if needed
                if (menu instanceof MenuGame)
                    if ( ((MenuGame)menu).hasNewHighScore() )
                        setHighScore( ((MenuGame)menu).getHighScore() );
                break;
			case CHANGE_CHAR:
				DiPoint.changeCharacter(getResources());
				break;
            default:
                break;
        }
    }

    public void draw(Canvas canvas)
    {
        //Draw Current Menu
        menu.draw(canvas);
    }

    //Actions
    public void onBackPressed()
    {
		//DiPoint.changeCharacter(getResources(), 1);
        if (!menu.isAnimating())
            if (menu instanceof MenuExtra)
                menu.destroy(Action.TO_MAIN_MENU);
            else
            if (menu instanceof MenuGame)
                ((MenuGame)menu).pause();
            else
                ExitGame();
    }

    public void ExitGame()
    {
        //Stop thread's execution
        running = false;

        //Close Activity
        ((GameActivity)getContext()).finish();
    }

    public void DestroyThread()
    {
        //Stop thread from executing
        running = false;

        //Keep trying to join thread until it stops executing
        boolean retry = true;
        while (retry)
            try
            {
                gThread.join();
                retry = false;
            } catch (InterruptedException e){}

        //Empty Thread
        gThread = null;
    }

    public int getHighScore()
    {
        return sharedPref.getInt("HIGH_SCORE", 0);
    }

    public void setHighScore(int gHighScore)
    {
        SharedPreferences.Editor editor = sharedPref.edit();
        editor.putInt("HIGH_SCORE", gHighScore);
        editor.apply();
    }

	public boolean hasSound()
	{
		return sharedPref.getBoolean("HAS_SOUND", true);
	}

    //Load Sounds
    public void loadSounds(int...soundId)
    {
        soundPool = new SoundPool(10, AudioManager.STREAM_MUSIC, 0);
        sound = new int[soundId.length];
        for (int iii = 0; iii < sound.length; iii++)
            sound[iii] = soundPool.load(getContext(), soundId[iii], 0);
    }

    public static void playSound(int soundNumber)
    {
		if (bSound)
        	soundPool.play(sound[soundNumber], 1.0f, 1.0f, 0, 0, 1.0f);
    }

    //Surface
    @Override
    public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {}

    @Override
    public void surfaceCreated(SurfaceHolder holder)
    {
        if (menu == null)
        {
            //Surface
            width  = getWidth();
            height = getHeight();
            density = getResources().getDisplayMetrics().density;
            isPhone = width /density < 640;

			sharedPref = ((GameActivity) getContext()).getPreferences(Context.MODE_PRIVATE);
			bSound = hasSound();

            //Font
            font.setColor(Color.WHITE);
            font.setTextSize( (20 +(isPhone? 0 : 12)) *GameSurface.density);
            font.setTextAlign(Paint.Align.CENTER);
            font.setAntiAlias(true);
            font.setShadowLayer(2, 1, 1, Color.BLACK);
        }
        else
            //Re-draw Menu State
            menu.forceDraw();

        //Create Thread
        gThread = new Thread(this);
        running = true;
        gThread.start();
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder)
    {
        DestroyThread();
    }

    //Thread
    public void run()
    {
        //Actual Screen
        Canvas screen;

        //Load Graphics
        if (!DiPoint.isLoaded())
        {
            //Loading Screen
            screen = null;
            //Try locking the canvas for pixel editing on surface
            try
            {
                screen = getHolder().lockCanvas();
                if (screen != null)
                    synchronized (getHolder())
                    {
                        screen.drawARGB(255, 254 ,158, 112);
                        screen.drawText("Loading", GameSurface.width/2, GameSurface.height/2, font);
                    }
            } finally{
                //Draw Loading screen
                if (screen != null)
                    getHolder().unlockCanvasAndPost(screen);}

            //Load graphics
            DiPoint.loadGraphics(getResources(),
                    R.drawable.background_bottom_0, //0
                    R.drawable.background_bottom_1,
                    R.drawable.background_top,

                    R.drawable.cloud_back, //3
                    R.drawable.cloud_front,

                    R.drawable.tree_0, //5
					R.drawable.tree_1,

                    R.drawable.title, //7
                    R.drawable.button,
					R.drawable.tutorial,

                    R.drawable.dark_dimension_logo, //10
                    R.drawable.facebook,
                    R.drawable.twitter,
                    R.drawable.tumblr,
                    R.drawable.google_play_store,

                    R.drawable.ground_0_0, //15
                    R.drawable.ground_1_0,
                    R.drawable.ground_2_0,
					R.drawable.ground_damaged_0,
					R.drawable.ground_damaged_1,
					R.drawable.ground_damaged_2,

                    R.drawable.crystal, //21
                    R.drawable.magic_mana,
                    R.drawable.shield,
					R.drawable.double_score,
                    R.drawable.spikes,

					R.drawable.sound_yes, //26
					R.drawable.sound_no,

                    R.drawable.darek_run_0, //28
                    R.drawable.darek_run_1,
                    R.drawable.darek_run_2,
                    R.drawable.darek_run_3,
                    R.drawable.darek_run_4,
                    R.drawable.darek_run_5,
					R.drawable.darek_run_6,
					R.drawable.darek_run_7,

                    R.drawable.darek_fall, //36
                    R.drawable.darek_jump,

                    R.drawable.shield_active_0, //38
					R.drawable.shield_active_1,

					R.drawable.air_jump_darek //40
            );

            //Load Sounds
            loadSounds(
                    R.raw.foot_step,
                    R.raw.jump,

                    R.raw.crystal_pick_up, //2
					R.raw.mana_collect,
					R.raw.mana_lose,
					R.raw.double_score,
					R.raw.shield,
									//7
					R.raw.spikes);
        }//Done loading graphics/sounds

        //If game is starting, go to MainMenu
        //(if menu != null then game is resuming so there is no need for change)
        if (menu == null)
        {
            menu = new MenuMain(getResources(), false);
            Background.Initialize();
        }

		Background.aCloud.startFromBeginning();

        //Game Cycle
        while (running)
        {
            //Start Frame
            long startTime = System.currentTimeMillis();

            //Update
            update();

            //Empty screen so it can obtain new instance
            screen = null;
            if (menu.needsToBeDrawn())
                //Try locking the canvas for pixel editing on surface
                try
                {
                    screen = getHolder().lockCanvas();
                    if (screen != null)
                        synchronized (getHolder())
                        {
                            //Actual drawing
                            draw(screen);

                            //Debug
                            //screen.drawText("Number of threads: " +Thread.activeCount(), 100, 100, font);
                            //screen.drawText("ms of this frame: " +(System.currentTimeMillis() -startTime), 100, 120, font);
                        }
                } finally{
                    //Draw changes
                    if (screen != null)
                        getHolder().unlockCanvasAndPost(screen);}

            //End Frame
            long endTime = System.currentTimeMillis();
            if (endTime -startTime < 1000/30)
                try { Thread.sleep(1000/30 -(endTime -startTime)); } catch (InterruptedException e){}
        } //While end
    } //run() end
}