package app.brest.utils.app.brest.game;

import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;

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

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;

import app.brest.testmin3d.ARActivity;
import app.brest.utils.JSONLoader;
import app.brest.utils.ResourceManager;
import app.brest.utils.SensorsManager;

/**
 * Created by ptitcois on 19/08/16.
 */
public class Game  implements Serializable {

    protected ArrayList<Area> mAreas = new ArrayList<Area>();
    protected ArrayList<Area> mCurrentStageAreas = new ArrayList<Area>();
    protected int             mNStages;
    protected int             mCurrentStage=0;
    protected Player          mPlayer;
    protected ResourceManager mResources;

    public Game(String name, ARActivity act)
    {
        JSONObject root = JSONLoader.load(act, name);

        mPlayer = new Player(act);
        try {
            JSONArray areas = root.getJSONArray("areas");
            for(int i=0; i<areas.length(); i++)
                mAreas.add(new Area(areas.getJSONObject(i)));
            mResources = new ResourceManager(this, act);
            findMaxStage();
            nextStage();

        } catch (JSONException e) {
            e.printStackTrace();
        }
    }


    public int getNStages() {
        return mNStages;
    }

    public int getCurrentStage() {
        return mCurrentStage;
    }

    public void findMaxStage()
    {
        mNStages=0;
        for(int i=0; i<mAreas.size(); i++) {
            if (mAreas.get(i).getStage() > mNStages)
                mNStages = mAreas.get(i).getStage();
        }
    }

    public boolean nextStage()
    {
        mCurrentStage++;
        if(mCurrentStage>mNStages) return true;

        loadStageAreasResources();
        mResources.nextStage(mCurrentStage);

        return false;
    }

    public void loadStageAreasResources()
    {
        mCurrentStageAreas.clear();
        for(int i=0; i<mAreas.size(); i++)
        {
            if(mAreas.get(i).getStage() == mCurrentStage)
                mCurrentStageAreas.add(mAreas.get(i));
        }
    }

    public int currentAreasCount()
    {
        return mCurrentStageAreas.size();
    }

    public Area getAreaStage(int i)
    {
        return mCurrentStageAreas.get(i);
    }

    public void removeArea(String name)
    {
        for(int i=0; i<mCurrentStageAreas.size(); i++)
            if(mCurrentStageAreas.get(i).getName() == name)
                mCurrentStageAreas.remove(i);
    }

    private void removeArea(int index)
    {
        mCurrentStageAreas.remove(index);
    }

    public boolean pickResource()
    {
        ArrayList<Resource> r = getResourcesNextToPlayer();
        for(int i=0; i<r.size(); i++) {
            for (int j = 0; j < mCurrentStageAreas.size(); j++)
                if (r.get(i).getName() == mCurrentStageAreas.get(j).getName()) {
                    removeArea(j);
                }
            mResources.pickUpResource(r.get(i).getName());
        }
        return mCurrentStageAreas.size()==0;
    }



    public String toString()
    {
        String out = "mAreas[]:\n";
        for(int i=0; i<mAreas.size(); i++)
            out+="\tmAres["+i+"] = "+mAreas.get(i).getJson().toString()+"\n";
        out+="\nmResourcesAcquired[] : \n";
        out+="mNStages :" +mNStages +"\n";
        out+="mCurrentStage" + mCurrentStage +"\n";
        return out;
    }

    public boolean save(Activity context)
    {
        try {
            FileOutputStream fos = context.openFileOutput("data", Context.MODE_PRIVATE);
            ObjectOutputStream os = new ObjectOutputStream(fos);
                os.writeObject(this);
            os.close();
            fos.close();
        } catch (IOException e) {
            e.printStackTrace();
            Log.e("SAVING", "Save failed:"+e.getMessage());
            return false;
        }
        Log.e("SAVING", "Save OK");
        return true;
    }

    public static Game load(Activity context)
    {
        try {
            FileInputStream fis = context.openFileInput("data");
            ObjectInputStream is = new ObjectInputStream(fis);
            Game obj = (Game) is.readObject();
            is.close();
            fis.close();
            return obj;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }


    public ArrayList<Resource> getAllResources(Activity act)
    {
        ArrayList<Resource> tmp = new ArrayList<Resource>();
        for(int i=0; i<mAreas.size(); i++)
            if(!tmp.contains(mAreas.get(i)))
                tmp.add(mAreas.get(i).getResource(act));
        return tmp;
    }

    public static boolean isSaved(Activity context)
    {
        boolean b = false;
        try {
            FileInputStream fis = context.openFileInput("data");
            if(fis!=null)
                b=true;
            fis.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return b;
    }

    public void onPause(Activity context)
    {
        save(context);
        mPlayer.onPause();
        removeCached3DModels();
    }


    public void onResume(ARActivity context)
    {
        mPlayer.onResume(context);
    }

    public void setSensorsManager(SensorsManager sm)
    {
        mPlayer.setSensorsManager(sm);
    }

    /**
     * Charge la ressource 3d quand on entre dans une zone
     */
    public boolean precache3DResource(Activity contecxt)
    {
        boolean b =false;
        for(int i=0; i<mAreas.size(); i++)
        {
            if(mAreas.get(i).getStage()==mCurrentStage &&  mAreas.get(i).isOnArea(mPlayer))
            {
                b=true;
                Resource r = mResources.getResourceLeftByName(mAreas.get(i).getResourceName());
                if(r!=null)
                    r.get3DModel(contecxt);
            }
        }
        return b;
    }


    /*
     *
     * Fonction principale de positionnnemnt et orientation
     *
     */
    public ArrayList<Resource> getResourcesNextToPlayer()
    {
        ArrayList<Resource> r = new ArrayList<Resource>();
        for(int i=0; i<mCurrentStageAreas.size(); i++)
        {
            //probleme de GPS..
            boolean b = mCurrentStageAreas.get(i).isOnArea(mPlayer);
            if(b)
            {

                if(mCurrentStageAreas.get(i).isOnDirection(mPlayer))
                {
                    r.add(mResources.getResourceLeftByName(mCurrentStageAreas.get(i).getResourceName()));
                }
            }
        }
        return r;
    }
    public String getResourcesNextToPlayer2()
    {
        String str = "Detected\n";
        ArrayList<Resource> r = new ArrayList<Resource>();
        for(int i=0; i<mCurrentStageAreas.size(); i++)
        {
            //probleme de GPS..
            if(mCurrentStageAreas.get(i).isOnArea(mPlayer))
            {

                str+="\t" +mCurrentStageAreas.get(i).getResourceName()+" "+mCurrentStageAreas.get(i).getDistanceToNextPlace(mPlayer)+" m\n";

            }
        }
        return str;
    }



    public Player getPlayer()
    {
        return mPlayer;
    }

    public void removeCached3DModels()
    {
        mResources.deleteAll3DModel();
    }

    public void newSensorManager(ARActivity act)
    {
        mPlayer.newSensorManager(act);
    }


}
