package macampcorp.macamp.activities;

import android.app.Activity;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AlertDialog;
import android.util.Log;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

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

import macampcorp.macamp.activities.fragments.BombFragment;
import macampcorp.macamp.activities.fragments.ChallengeFragment;
import macampcorp.macamp.activities.fragments.QCMFragment;
import macampcorp.macamp.activities.fragments.QRCodeFragment;
import macampcorp.macamp.activities.fragments.QuestionFragment;
import macampcorp.macamp.activities.viewers.ImageViewerActivity;
import macampcorp.macamp.activities.viewers.MediaViewerAcitvity;
import macampcorp.macamp.activities.viewers.ResourceListActivity;
import macampcorp.macamp.game.Bomb;
import macampcorp.macamp.game.Game;
import macampcorp.macamp.game.Resource;
import macampcorp.macamp.game.Stage;
import macampcorp.macamp.game.challenges.Challenge;
import macampcorp.macamp.game.Indice;
import macampcorp.macamp.game.scheduler.Scheduler;
import macampcorp.macamp.game.scheduler.SpecialTask;
import macampcorp.macamp.lang.Locale;
import macampcorp.macamp.utils.AndroidResources;
import macampcorp.macamp.utils.L;


public class HostActivity extends Activity implements ChallengeFragment.OnFragmentInteractionListener {
    public static final int REQUEST_CODE = 25;
    protected Game mGame;
    protected TextView mUITimeLeft;
    protected TextView mUICode;
    protected Button   mUIButtonVideos;
    protected Button   mUIButtonIndice;
    protected Button   mUIButtonValid;

    protected QCMFragment mQCMFragment;
    protected QRCodeFragment mQRCodeFragment;
    protected QuestionFragment mQuestionFragment;
    protected BombFragment mBombFragment;
    protected ChallengeFragment mCurrentFragment;
    protected Challenge mCurrentChallenge;

    private static final int ACTIVITY_RESULT_RESOURCE_VIEWER_SCHEDULER = 2;

    public String _(int x)
    {
        return  getResources().getString(x);
    }

    private Timer mTimer;
    private Runnable mTimerTick = new Runnable() {
        public void run() {
            if(!mGame.getBomb().hasExplosed())
            {
                mUITimeLeft.setText(mGame.getBomb().getTimeBeforeBoom());
            }else
            {
                mTimer.cancel();
                mUITimeLeft.setText("BOOM !");
                onExplose();
            }
        }
    };

    public void onHelp(View v)
    {
        TutoActivity.start(this);
    }



    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_host);

        mQCMFragment = QCMFragment.newInstance();
        mQuestionFragment = QuestionFragment.newInstance();
        mQRCodeFragment = QRCodeFragment.newInstance();
        mBombFragment = BombFragment.newInstance();
        mUIButtonVideos = (Button) findViewById(R.id.btn_videos);
        mUIButtonIndice = (Button) findViewById(R.id.btn_indice);
        mUIButtonValid = (Button) findViewById(R.id.btn_valid);

        mGame=Game.game();

        mUITimeLeft = findViewById(R.id.tv_car);
        mUICode = findViewById(R.id.tv_code);

        mTimer = new Timer();
        mTimer.schedule(new TimerTask() {
            @Override
            public void run() {
                timerCallback();
            }

        }, 0, 1000);

        updateCode();

        if(mGame.getCurrentStageIndex()<0) { //noueau jeu
            mGame.nextStage(this);
            mGame.getScheduler().schedule(this, mGame);
        }
        else
        {
            initFromLoad();
        }
    }

    public void initFromLoad()
    {
        mGame.getScheduler().undo();
        mGame.getScheduler().schedule(this, mGame);
    }

    public   void setFragment(Challenge c)
    {
        Class type = c.getStartWith();
        mCurrentChallenge=c;
        ChallengeFragment f = null;

        if(type.isInstance(mQCMFragment))
            f= mQCMFragment;
        else if(type.isInstance(mQRCodeFragment))
            f= mQRCodeFragment;
        else if(type.isInstance(mQuestionFragment))
            f= mQuestionFragment;
        else if(type.isInstance(mBombFragment))
            f=mBombFragment;
        else {
            throw new RuntimeException("Erreur: La classe de fragment est null");
        }

        if(f!=mCurrentFragment)
        {
            mCurrentFragment=f;
            FragmentManager fm = getFragmentManager();
            FragmentTransaction ft = fm.beginTransaction();
            ft.replace(R.id.container, mCurrentFragment);
            ft.commit();
        }
        else
        {
            onReady(c);
        }
    }

    public void onReady(Challenge chall) {
        mCurrentFragment.initChallenge(chall);
    }

    public void onFragmentInteraction(Uri uri) {}


    public void onTryDisarm(View v)
    {
        Scheduler sched = mGame.getScheduler();
        sched.undo();
        sched.prepend(SpecialTask.BOMB);
        sched.schedule(this, mGame);
    }


    private void timerCallback()
    {
        this.runOnUiThread(mTimerTick);
    }

    private void updateCode()
    {
        Log.e("--------", "Bomb: "+mGame.getBomb().getPasswordKnown());
        mUICode.setText(mGame.getBomb().getPasswordKnown());
    }

    public void onClickValid(View v)
    {
        if(mCurrentFragment!=null && mCurrentFragment.getChallenge()!=null)
        {
            int res = mCurrentFragment.check();
            if(res==Challenge.OK)
            { //bonne réponse
                challengeValidate(mCurrentFragment.getChallenge(),  mGame, this);
            }else if(res==Challenge.FAIL)
            { //mauvaise réponse
                //réponse facultative
                if(!mCurrentFragment.getChallenge().isMandatory())
                {
                    mCurrentFragment.onChallengePassed();
                    challengeValidate(mCurrentFragment.getChallenge(),  mGame, this);
                    mGame.getBomb().addTime(-mCurrentFragment.getChallenge().getPenality());
                }else //réponse obligatoire
                {
                    mCurrentFragment.onChallengeFailed();
                    mGame.getBomb().addTime(-mCurrentFragment.getChallenge().getPenality());
                }
            }
        }else
        {
            throw new RuntimeException("Erreur onClickValid, le fragment ou le challenge est nul...");
        }
    }

    public void onClickVideos(View v)
    {
        ResourceListActivity.start(this);
    }



    public void discoverIndice()
    {
        Indice ind = mCurrentFragment.showIndice();
        if(ind!=null && ind.getPenality()>0)
            mGame.getBomb().addTime(-ind.getPenality());

        new AlertDialog.Builder(this)
                .setTitle("Indice:")
                .setMessage(ind.getText())
                .setPositiveButton(android.R.string.yes, null)
            .create().show();

        if(!mCurrentFragment.getChallenge().hasNextIndice())
            mUIButtonIndice.setVisibility(View.INVISIBLE);
        save();
    }

    public void onClickIndice(View v)
    {
        if(mCurrentFragment!=null && mCurrentFragment.getChallenge() !=null)
        {
            Indice x = mCurrentFragment.getChallenge().peakNextIndice();
            int c = Math.round(x.getPenality()*60);
            String out = ""+c+" "+_(R.string.secondes);
            if(c>=60)
                out=(c/60)+" "+_(R.string.secondes)+" "+
                        _(R.string.and)+" "+(c%60)+" "+_(R.string.minutes);

            new AlertDialog.Builder(this)
                    .setTitle(_(R.string.dialog_sure_title))
                    .setMessage(_(R.string.dialog_sure_pre)+out+
                                _(R.string.dialog_sure_post))
                    .setNegativeButton(android.R.string.no,  null)
                    .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface arg0, int arg1) {
                            discoverIndice();
                        }
                    }).create().show();
        }
    }

    public void onExplose()
    {
        setFailed();
    }

    public void setVisibilityView(int res, int state)
    {
        View v = findViewById(res);
        if(v!=null) v.setVisibility(state);
    }

    public void setVisibilityView(int[] res, int state)
    {
        for(int i=0; i<res.length; i++)
            setVisibilityView(res[i], state);
    }

    public Challenge nextChallenge() {
        Stage oldStage = mGame.getCurrentStage();
        Challenge c = mGame.nextChallenge(this);
        Stage s = mGame.getCurrentStage();
//        Log.e("___SCHEDULER_PRESQUE","\t->"+ c +" stage : "+s.getName());
        if(c!=null)
        {
            mGame.getScheduler().append(c);
        }else if(s!=null) //new stage
        {
            mGame.getBomb().addKnownCharacter(oldStage.getCharIndex());
            updateCode();
        }else{
            Scheduler sched = mGame.getScheduler();
            sched.undo();
            sched.prepend(SpecialTask.BOMB);
            sched.schedule(this, mGame);
        }
        return c;
    }



    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode)
        {
            case CreditsActivity.REQUEST_CODE:
            case MediaViewerAcitvity.REQUEST_CODE:
            case BombActivity.REQUEST_CODE:
            case ImageViewerActivity.REQUEST_CODE:
            case TutoActivity.REQUEST_CODE:
                mGame.getScheduler().schedule(this, mGame);
                save();
            break;

            case EndActivity.REQUEST_CODE:
                finish();
                break;

        }
    }

    public void startResource(Resource r)
    {
        Intent intent = AndroidResources.getViewerIntent(this, r);
        startActivityForResult(intent, AndroidResources.getViewerRequestCode(r));
    }

    public void _challengeValidate(Challenge c, Game g, HostActivity dri, boolean ok) {
        if(ok)
            mGame.getBomb().addKnownCharacter(c.getCharIndex());
        updateCode();
        nextChallenge();

        mGame.getScheduler().schedule(this, mGame);
        save();
    }

    public void challengeValidate(Challenge c, Game g, HostActivity dri) {
        _challengeValidate(c,g,dri,true);
    }

    public void challengePassed(Challenge c, Game g, HostActivity dri)
    {
        _challengeValidate(c,g,dri,false);
    }

    public Challenge currentChallenge() {
        return mCurrentChallenge;
    }



    public void setFinished()
    {
        mTimer.cancel();
        mGame.getScheduler().clear();
        L.error("__SCHEDULER_DEBUG__", "Win");
        L.error("__SCHEDULER_DEBUG__","clear:"+ mGame.getScheduler().getTaskListString());
        mGame.getScheduler().append(mGame.getOnWin().getStartEvent());
        L.error("__SCHEDULER_DEBUG__", "start:"+mGame.getScheduler().getTaskListString()+ " -> "+mGame.getOnLoose().getStartEvent().size());
        mGame.getScheduler().append(mGame.getOnWin().getResources());
        L.error("__SCHEDULER_DEBUG__", "res:"+mGame.getScheduler().getTaskListString());
        mGame.getScheduler().append(mGame.getOnWin().getEndEvent());
        L.error("__SCHEDULER_DEBUG__", "end:"+mGame.getScheduler().getTaskListString());
        mGame.getScheduler().append(SpecialTask.END_SUCCESS);
        mGame.getScheduler().schedule(this, mGame);

    }

    public void setFailed()
    {
        mTimer.cancel();
        mGame.getScheduler().clear();
        L.error("__SCHEDULER_DEBUG__", "Loose");
        L.error("__SCHEDULER_DEBUG__","clear:"+ mGame.getScheduler().getTaskListString());
        mGame.getScheduler().append(mGame.getOnLoose().getStartEvent());
        L.error("__SCHEDULER_DEBUG__", "start:"+mGame.getScheduler().getTaskListString()+ " -> "+mGame.getOnLoose().getStartEvent().size());
        mGame.getScheduler().append(mGame.getOnLoose().getResources());
        L.error("__SCHEDULER_DEBUG__", "res:"+mGame.getScheduler().getTaskListString());
        mGame.getScheduler().append(mGame.getOnLoose().getEndEvent());
        L.error("__SCHEDULER_DEBUG__", "end:"+mGame.getScheduler().getTaskListString());
        mGame.getScheduler().append(SpecialTask.END_FAILED);
        mGame.getScheduler().schedule(this, mGame);

    }

    public Activity getActivity() {
        return this;
    }

    public void load() {
        mGame = Game.load(this);
        Game.setGame(mGame);
    }

    public void save() {
        mGame.save(this);
    }

    @Override
    public void onBackPressed()
    {
        if(mCurrentFragment==null || mCurrentFragment.onBackPressed())
            super.onBackPressed();
    }

    public static HostActivity cast(Activity v)
    {
        if(v instanceof HostActivity) return (HostActivity) v;
        throw new RuntimeException("Erreur l'activity n'est pas 'HostActivity' : '"+v.getClass().getName()+"'");
    }



    public static void startGame(Activity a)
    {
        startGame(a,false, "game_medium");
    }

    public static void startGame(Activity a, boolean b)
    {
        startGame(a,b, "game_medium");
    }


    public static void startGame(Activity a, String b)
    {
        startGame(a,false, b);
    }


    public static void startGame(Activity a, boolean erase, String file)
    {
        if(erase)
        {
            Game.erase(a);
            Game.setGame(null);
        }

        if(Game.game()==null)
        {
            Game g = Game.load(a);
            if (g != null ) {
                Game.setGame(g);
                Toast.makeText(a, R.string.game_loading, Toast.LENGTH_SHORT).show();
            } else {
                Game game = new Game(file, a);
                Game.setGame(game);
                Toast.makeText(a, R.string.game_new, Toast.LENGTH_SHORT).show();
            }
        }

        Intent intent = new Intent(a, HostActivity.class);
        a.startActivityForResult(intent, HostActivity.REQUEST_CODE);
    }

}