package macampcorp.macamp.game;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.widget.Toast;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;

import macampcorp.macamp.activities.HostActivity;
import macampcorp.macamp.activities.TutoActivity;
import macampcorp.macamp.exceptions.BadConfigFileException;
import macampcorp.macamp.utils.L;

public class Event implements Serializable {

    class EventParam implements  Serializable
    {
        static final int EVT_PARAM_INT = 0;
        static final int EVT_PARAM_FLOAT = 1;
        static final int EVT_PARAM_STRING = 2;

        int type;
        int iValue;
        String sValue;
        double dValue;

        EventParam(Object x) {
            if(x instanceof Integer || x instanceof Long || x instanceof  Byte || x instanceof Short){
                iValue=(int)x;
                type=EVT_PARAM_INT;
            }
            else if(x instanceof Double || x instanceof Float){
                dValue=(double)x;
                type=EVT_PARAM_FLOAT;
            }else if(x instanceof String){
                sValue=(String)x;
                type=EVT_PARAM_STRING;
            }
        }

        int optInt(int def){ if(type!=EVT_PARAM_INT) return def; return iValue;}
        double optDouble(double def){ if(type!=EVT_PARAM_FLOAT) return def; return dValue;}
        String optString(String def){ if(type!=EVT_PARAM_STRING) return def; return sValue;}

    }

    private String mMethod;
    private ArrayList<EventParam> mArgs = new ArrayList<EventParam>();

    public class EventReturn  implements  Serializable{
        public int code;
        public boolean wait=false;
        public String message;
        public ArrayList<Object> args;

        public EventReturn() { }
        public EventReturn(int c) { code=c;}
        public EventReturn(int c, String m) { code=c; message=m;}
        public EventReturn(int c, String m, ArrayList<Object> a) { code=c; message=m; args=a;}


        public EventReturn set(int c, String m) { code=c; message=m; return this;}
        public EventReturn addArg(Object e) {args.add(e); return this;}
        public void setWait(){ wait=true;}

        public boolean isError() { return code!=0;}
    }

    public Event(JSONObject j)
    {
        try {
            mMethod = j.getString("method");
        } catch (JSONException e) {
            e.printStackTrace();
            throw new BadConfigFileException("(Event) Bad parameter 'method' :" +e.getMessage());
        }

        try {
            JSONArray arr  = j.getJSONArray("args");
            for(int i=0; i<arr.length(); i++)
                mArgs.add(new EventParam(arr.get(i)));
        } catch (JSONException e) {
        }
    }

    public EventReturn exec(HostActivity a, Game g)
    {
        Class[] paramType = new Class[2];
        paramType[0] = HostActivity.class;
        paramType[1] = Game.class;
        EventReturn ev =  new EventReturn();


        try {
            Method method = this.getClass().getDeclaredMethod(mMethod, paramType);
            return (EventReturn) method.invoke(this, a, g);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
            ev.set(-1, "NoSuchMethodException");
            return ev.addArg(e);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
            ev.set(-2, "NoSuchMethodException");
            return ev.addArg(e);
        } catch (InvocationTargetException e) {
            e.printStackTrace();
            ev.set(-3, "InvocationTargetException");
            return ev.addArg(e);
        }
    }

    private int argAsInt(int i, int def) { return mArgs.get(i).optInt(def); }
    private double argAsDouble(int i, double def) { return mArgs.get(i).optDouble(def);  }
    private String argAsString(int i, String def) { return mArgs.get(i).optString(def); }



    public EventReturn armBomb(HostActivity a, Game g)
    {
        g.getBomb().arm();
        return new EventReturn(0,"OK");
    }


    /**
     * Si temps > $0 alors temps=$0
     * $0 : temps en minutes
     * @return OK
     */
    public EventReturn setTimerTo(HostActivity a, Game g)
    {
        long time = g.getBomb().getSecondsBeforeBoom();
        long seuil = argAsInt(0, 15) * 60;
        long newTime = (time>seuil)?seuil:time;
        g.getBomb().setSecondsBeforeBoom(newTime);
        return new EventReturn(0,"OK");
    }


    public EventReturn print(HostActivity a, Game g)
    {
        Toast.makeText(a, argAsString(0, "Error"), Toast.LENGTH_LONG).show();
        L.info(  argAsString(0, "Error"));
        return new EventReturn(0,"OK");
    }

    public EventReturn alert(final HostActivity a, final Game g)
    {
        String message = argAsString(0, "");
        AlertDialog.Builder builder = new AlertDialog.Builder(a);
        // Add the buttons
        builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int id) {
                g.getScheduler().schedule(a, g);
            }
        });
        builder.setNegativeButton("Non", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int id) {
                g.getScheduler().schedule(a, g);
            }
        });
        // Set other dialog properties
        builder.setMessage(message);
        L.debug(message);

        // Create the AlertDialog
        AlertDialog dialog = builder.create();
        dialog.show();
        EventReturn ev = new EventReturn(0, "OK");
        ev.setWait();
        return ev;
    }

    public EventReturn tuto(HostActivity a, Game g)
    {
        TutoActivity.start(a);
        EventReturn ev = new EventReturn(0, "OK");
        ev.setWait();
        return ev;
    }

    public String getMethod() {
        return mMethod;
    }

    public ArrayList<EventParam> getArgs() {
        return mArgs;
    }
}
