package com.lloydm.javakogengine;

import java.io.IOException;

import android.annotation.SuppressLint;
import android.app.Service;
import android.content.Intent;
import android.content.res.AssetFileDescriptor;
import android.content.res.AssetManager;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.util.Log;

@SuppressLint("HandlerLeak")
public class MenuMusicService extends Service
{
    private static MediaPlayer menumediaplayer;

    public volatile static boolean audiomuted = false;

    private static volatile boolean threadrunning = false;
    private volatile int cmd = -1;
    private static Handler handler;

    private final float volume = (float) (1 - (Math.log(80) / Math.log(100)));

    private final static int CMD_PLAY = 0;
    private final static int CMD_PAUSE = 1;
    private final static int CMD_FADEOUT = 2;
    private final static int CMD_FADEIN = 3;
    private final static int CMD_FINISH = 4;
    private final static int CMD_START = 5;

    // volume on/off
    private final static int CMD_MUTEON = 6;
    private final static int CMD_MUTEOFF = 7;

    private volatile boolean usecustommusic = false;
    private String custommusicfilename = "";

    private final static String TAG = "com.lloydm.javakogengine.MenuMusicService";

    private static AssetManager assetmgr = null;

    @Override
    public void onCreate()
    {

    }

    @Override
    public IBinder onBind(Intent intent)
    {

        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId)
    {
        if (intent == null)
        {
            return START_STICKY;
        }
        String action = intent.getAction();
        if (action != null)
        {
            if (action.equals("com.lloydm.javakogengine.MenuMusicService.start"))
            {
                cmd = CMD_START;
                // init, load and begin playback....
                if (!threadrunning)
                {
                    threadrunning = true;
                    new Thread(new Runnable()
                    {

                        @Override
                        public void run()
                        {

                            initmusic();
                            Looper.prepare();
                            handler = new Handler()
                            {
                                public void handleMessage(Message msg)
                                {
                                    switch (msg.what)
                                    {
                                    case CMD_MUTEON:
                                        if (menumediaplayer != null)
                                        {
                                            try
                                            {
                                                Log.i(TAG, "muting audio");
                                                audiomuted = true;
                                                menumediaplayer.setVolume(0, 0);
                                                Log.i(TAG, "audio muted");
                                            }
                                            catch (Exception e)
                                            {
                                                Log.e(TAG, "music player in wrong state");
                                            }
                                        }
                                        else
                                        {
                                            Log.w(TAG, "Music player should be available but isn't");
                                        }
                                        break;
                                    case CMD_MUTEOFF:
                                        if (menumediaplayer != null)
                                        {
                                            try
                                            {
                                                Log.i(TAG, "unmuting audio");
                                                audiomuted = false;
                                                menumediaplayer.setVolume(volume, volume);
                                                Log.i(TAG, "audio unmuted");
                                            }
                                            catch (Exception e)
                                            {
                                                Log.e(TAG, "music player in wrong state");
                                            }
                                        }
                                        else
                                        {
                                            Log.w(TAG, "Music player should be available but isn't");
                                        }

                                        break;
                                    case CMD_PLAY:
                                        handler.removeCallbacksAndMessages(null);
                                        if (menumediaplayer != null)
                                        {
                                            try
                                            {
                                                if (!menumediaplayer.isPlaying())
                                                {
                                                    menumediaplayer.start();
                                                    if (!audiomuted)
                                                    {
                                                        menumediaplayer.setVolume(volume, volume);
                                                    }
                                                    else
                                                    {
                                                        menumediaplayer.setVolume(0, 0);
                                                    }
                                                }
                                            }
                                            catch (Exception e)
                                            {
                                                Log.e(TAG, "music player in wrong state");
                                            }
                                        }
                                        else
                                        {
                                            Log.w(TAG, "Music player should be available but isn't");
                                        }
                                        break;

                                    case CMD_PAUSE:
                                        handler.removeCallbacksAndMessages(null);
                                        if (menumediaplayer != null)
                                        {
                                            try
                                            {
                                                if (menumediaplayer.isPlaying())
                                                {
                                                    menumediaplayer.pause();
                                                }
                                            }
                                            catch (Exception e)
                                            {
                                                Log.e(TAG, "music player in wrong state");
                                            }
                                        }
                                        else
                                        {
                                            Log.w(TAG, "Music player should be available but isn't");
                                        }

                                        break;

                                    case CMD_FINISH:
                                        finishmusic();
                                        handler.removeCallbacksAndMessages(null);
                                        handler.getLooper().quit();
                                        threadrunning = false;
                                        stopSelf(); // important!
                                        break;

                                    default: // currently fade in and fade out will come here - not used yet...
                                        handler.removeCallbacksAndMessages(null);
                                        break;
                                    }
                                }
                            };

                            Looper.loop();
                            Message msg = new Message();
                            msg.what = cmd;
                            if (handler != null)
                            {
                                handler.sendMessage(msg);
                            }
                        }
                    }).start();
                }
                else
                {
                    // cancel the CMD_FINISH if it is there.....ie get in early! - assumes there was a 'resume' command
                    // which was to start the process again between activity onpause/onresumes...
                    // we should probably try and run a 'play' command....regardless...just in case...
                    if (handler != null)
                    {
                        try
                        {
                            handler.removeMessages(CMD_FINISH);
                        }
                        catch (Exception e)
                        {
                            Log.e(TAG, "Error - failed to cancel finish command");
                        }
                        try
                        {
                            Message msg2 = new Message();
                            msg2.what = CMD_PLAY;
                            handler.sendMessage(msg2);
                        }
                        catch (Exception e)
                        {
                            Log.e(TAG, "Error - failed to play music 123");
                        }
                    }
                }
            }
            if (action.equals("com.lloydm.javakogengine.MenuMusicService.muteon"))
            {
                try
                {
                    cmd = CMD_MUTEON;
                    Message msg = new Message();
                    msg.what = cmd;
                    if (handler != null)
                    {
                        handler.sendMessage(msg);
                    }
                }
                catch (Exception e)
                {
                    Log.w(TAG, "handler problem when muting");
                }
            }
            if (action.equals("com.lloydm.javakogengine.MenuMusicService.muteoff"))
            {
                try
                {
                    cmd = CMD_MUTEOFF;
                    Message msg = new Message();
                    msg.what = cmd;
                    if (handler != null)
                    {
                        handler.sendMessage(msg);
                    }
                }
                catch (Exception e)
                {
                    Log.w(TAG, "handler problem when unmuting");
                }
            }
            if (action.equals("com.lloydm.javakogengine.MenuMusicService.play"))
            {
                cmd = CMD_PLAY; // resume basically...
                Message msg = new Message();
                msg.what = cmd;
                if (handler != null)
                {
                    handler.sendMessage(msg);
                }
            }
            if (action.equals("com.lloydm.javakogengine.MenuMusicService.pause"))
            {
                cmd = CMD_PAUSE;
                // if the music is playing then pause it.....(temporarily)
                Message msg = new Message();
                msg.what = cmd;
                if (handler != null)
                {
                    handler.sendMessage(msg);
                }
            }
            if (action.equals("com.lloydm.javakogengine.MenuMusicService.fadeout"))
            {
                cmd = CMD_FADEOUT;
                // fade out to 0.1 volume...
                Message msg = new Message();
                msg.what = cmd;
                if (handler != null)
                {
                    handler.sendMessage(msg);
                }
            }
            if (action.equals("com.lloydm.javakogengine.MenuMusicService.fadein"))
            {
                cmd = CMD_FADEIN;
                // fade in to maxvolume (0.4f?)
                Message msg = new Message();
                msg.what = cmd;
                if (handler != null)
                {
                    handler.sendMessage(msg);
                }
            }
            if (action.equals("com.lloydm.javakogengine.MenuMusicService.finish"))
            {
                cmd = CMD_FINISH;
                // release all resources and stop playing etc...kill the looper etc...
                Message msg = new Message();
                msg.what = cmd;
                if (handler != null)
                {
                    handler.sendMessageDelayed(msg, 2750);
                }

            }
            if (action.equals("com.lloydm.javakogengine.MenuMusicService.instantkill"))
            {
                cmd = CMD_FINISH;
                // release all resources and stop playing etc...kill the looper etc...
                Message msg = new Message();
                msg.what = cmd;
                if (handler != null)
                {
                    handler.sendMessageDelayed(msg, 1000); // almost instant...not quite!
                }

            }

        }
        return START_STICKY;
    }

    private static void finishmusic()
    {
        if (menumediaplayer != null)
        {
            Log.i(TAG, "ending any music");
            try
            {
                if (menumediaplayer.isPlaying())
                {
                    menumediaplayer.stop();
                }
            }
            catch (Exception e)
            {
                Log.e(TAG, "Music player not in right state");
            }
            Log.i(TAG, "Releasing music player");
            menumediaplayer.release();
            menumediaplayer = null;
        }

    }

    private void initmusic()
    {
        // get default system volume for app.....
        if (menumediaplayer != null)
        {
            Log.i(TAG, "Releasing music player");
            menumediaplayer.release();
            menumediaplayer = null;
        }
        Log.i(TAG, "new media player");
        menumediaplayer = new MediaPlayer();
        menumediaplayer.reset();
        Log.i(TAG, "setting stream type and volume music player");
        menumediaplayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
        if (!audiomuted)
        {
            menumediaplayer.setVolume(volume, volume);
        }
        {
            menumediaplayer.setVolume(0, 0);
        }
        menumediaplayer.setOnErrorListener(new MediaPlayer.OnErrorListener()
        {
            @Override
            public boolean onError(MediaPlayer mp, int what, int extra)
            {
                Log.e(TAG, "Error with media player:what:" + what + " extra:" + extra);
                return true;
            }
        });

        

        loadaudiotrack();
    }

    
    private void loadaudiotrack()
    {
        if (menumediaplayer != null)
        {
            // pick a track at random.....
            AssetFileDescriptor fd = null;
            if (usecustommusic)
            {

            }
            else
            {
                try
                {
                    if (assetmgr == null)
                    {
                        assetmgr = getAssets();
                    }
                    fd = assetmgr.openFd("media/mod/hulk/space01long.ogg");
                }
                catch (IOException e)
                {
                	Log.e(TAG,"IO Exception reading music");
                    e.printStackTrace();
                }
            }

            if (fd != null || usecustommusic == true)
            {
                try
                {
                    Log.i(TAG, "setting data source for music");
                    if (fd != null)
                    {
                        menumediaplayer.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength());
                        fd.close();
                    }
                    else
                    {
                        menumediaplayer.setDataSource(custommusicfilename);
                    }
                    menumediaplayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener()
                    {
                        @Override
                        public void onPrepared(MediaPlayer mp)
                        {
                            // then start playing!
                            if (menumediaplayer != null)
                            {
                                if (menumediaplayer != mp)
                                {
                                    return;
                                }
                            }
                            mp.start();
                            if (!audiomuted)
                            {
                                mp.setVolume(volume, volume);
                            }
                            else
                            {
                                mp.setVolume(0, 0);
                            }
                        }
                    });
                    menumediaplayer.setLooping(true);

                    // set the volume...or mute it altogether.....
                    menumediaplayer.prepareAsync();

                }
                catch (IllegalArgumentException e1)
                {

                    e1.printStackTrace();
                    Log.e(TAG, "Error opening music file - illegala rgument");
                }
                catch (IllegalStateException e1)
                {
                    Log.e(TAG, "Error opening music file- illegal state");
                    e1.printStackTrace();
                }
                catch (IOException e1)
                {
                    Log.e(TAG, "Error opening music file - io exception");
                    e1.printStackTrace();
                }
                try
                {
                    if (fd != null)
                    {
                        fd.close();
                    }
                }
                catch (IOException e)
                {
                    Log.i(TAG, "Error closing audio file - potentially already closed");
                }
            }

        }
    }

}
