package com.example.theviper;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Point;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Display;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SurfaceView;
import android.view.View;
import android.view.WindowManager;
import android.widget.TextView;

import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.CameraBridgeViewBase;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Size;
import org.opencv.imgproc.Imgproc;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

@SuppressLint("NewApi")
public class CrearMapa extends Activity implements CameraBridgeViewBase.CvCameraViewListener2, View.OnClickListener
{
    /////////////
    //VARIABLES//
    /////////////
    private static final String TAG = "CrearMapa:";

    private TextView toma_captura; //texto que usaremos como boton

    private CameraBridgeViewBase mOpenCvCameraView;
    //Configuracion de la camara
    private int cam_type = 0; // 1 for front camera, 0 for back camera
    private int cam_width = (int) 640;//1280;  //640
    private int cam_high = (int) 480;//720;    //480

    //VARIABLES QUE CONTIENEN IMAGENES PARA EL PROCESAMIENTO
    private Mat input; //imagen capturada
    private Mat iGray;//Frame computed in gray slace
    private Mat output;//salida
    private int tamanyo_cuadrado = 5; // 5 //2;//CUIDADO! Que la resolución sea divisible entre este número!
    private int umbral = (tamanyo_cuadrado^2)/2; //debe tener un valor alrededor de (tamanyo_cuadrado^2)/2
    private double [] dataRed = {200,0,0,255}; //color del cuadradito

    private static String FICHERO = Environment.getExternalStorageDirectory() + "/TheViper/mapa.txt";
    private int [] mapa; //mapa del juego, se le pasara a la actividad VistaJuego

    /////////////////////////
    //DEFINIR CICLO DE VIDA//
    /////////////////////////
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        Log.i(TAG, "metodo onCreate ha sido llamado");
        super.onCreate(savedInstanceState);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        setContentView(R.layout.crearmapa);

        //PARA LA CAMARA
        //Se usara JavaCameraView en lugar de la nativa para mayor compatibilidad
        mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.TheViper_activity_java_surface_view);
        mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE);
        mOpenCvCameraView.setCvCameraViewListener(this);

        //PARA EL TEXTVIEW
        toma_captura = (TextView)findViewById(R.id.textViewCapturar);
        toma_captura.setOnClickListener(this);

        //PARA EL MAPA
        // Obtengo resolucion de la pantalla y calculo variables que dependen de ella
        /*WindowManager windowManager = (WindowManager) this.getSystemService(Context.WINDOW_SERVICE);
        Display display = windowManager.getDefaultDisplay();
        Point size = new Point();
        display.getSize(size);
        int resolucion_pantallaX = size.x;
        int resolucion_pantallaY = size.y;
        cam_width = resolucion_pantallaX;//
        cam_high = resolucion_pantallaY;*/
        mapa = new int[(cam_width/tamanyo_cuadrado) * (cam_high/tamanyo_cuadrado)]; //inicializo la matriz del mapa
    }

    @Override
    public void onPause()
    {
        super.onPause();
        if (mOpenCvCameraView != null)
            mOpenCvCameraView.disableView();
    }

    @Override
    public void onResume()
    {
        super.onResume();
        OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_3, this, mLoaderCallback);
    }

    public void onDestroy() {
        super.onDestroy();
        if (mOpenCvCameraView != null)
            mOpenCvCameraView.disableView();
    }

    ///////////////////////////////////////
    //EVENTO ONCLICK DEL BOTON DE CAPTURA//
    ///////////////////////////////////////
    public void onClick(View arg0) {
        if (mOpenCvCameraView != null)
            mOpenCvCameraView.disableView();
        toma_captura.setText(getResources().getString(R.string.Capturando));
        Intent intent = new Intent(CrearMapa.this, MainActivity.class);

        try{
            // Creo el directoio para guardar el fichero
            File dir = new File(Environment.getExternalStorageDirectory() + "/TheViper//");

            // si el direcctorio no existe, lo creo
            if (!dir.exists()) {
                dir.mkdir();
            }
            FileOutputStream f = new FileOutputStream(FICHERO, false);
            for(int i=0; i< mapa.length;i++)
            {
                String aux = mapa[i]+"";
                f.write(aux.getBytes());
            }

            f.close();
        } catch (FileNotFoundException e)
        {
            Log.e("Onclick Captura", e.getMessage(),e);
        }catch (IOException e)
        {
            Log.e("Onclick Captura", e.getMessage(),e);
        }

        startActivity(intent);
        finish(); //Evita que vuelva a esta actividad

    }


    //////////////////////////////////////
    //DEFINIR TRATAMIENTO DIGITAL IMAGEN//
    //////////////////////////////////////

    //Initializa OpenCV Manager
    private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
        @Override
        public void onManagerConnected(int status) {
            switch (status) {
                case LoaderCallbackInterface.SUCCESS:
                    //Se ha inicializado correctamente
                {
                    mOpenCvCameraView.disableView();
                    mOpenCvCameraView.setCameraIndex(cam_type);
                    mOpenCvCameraView.setMaxFrameSize(cam_width,cam_high);
                    mOpenCvCameraView.enableView();
                    Log.i(TAG, "OpenCV se ha cargado correctamente");

                } break;
                //Error
                default:
                {
                    super.onManagerConnected(status);
                } break;
            }
        }
    };

    public void reiniciarCamara()
    {
        mOpenCvCameraView.disableView();
        mOpenCvCameraView.setCameraIndex(cam_type);
        mOpenCvCameraView.setMaxFrameSize(cam_width,cam_high);
        mOpenCvCameraView.enableView();
    }


    //Cuando se inicia la camara
    public void onCameraViewStarted(int width, int height)
    {
        Log.i(TAG, "Se ha iniciado la captura ");
        //Inicializo matrices
        input = new Mat(width, height, CvType.CV_8UC4);
        output = new Mat(width, height, CvType.CV_8UC4);
        iGray = new Mat(cam_width, cam_high, CvType.CV_8UC1);
        // 	Si queremos cargar una imagen desde los recursos
        // 	bitmap = BitmapFactory.decodeResource(getResources(), R.raw.initial);
        // 	Utils.bitmapToMat(bitmap, output);
    }

    //Cuando se detiene la captura de fotos
    public void onCameraViewStopped()
    {
        Log.i(TAG, "Capture has been stopped ");
    }

    ////////////////////////////////////////////////
    // Procesa cada captura tomada por la camara  //
    ////////////////////////////////////////////////
    public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame)
    {
        input = inputFrame.rgba(); //convierte la captura en formato RGB
        //covierto a escala de grises
        Imgproc.cvtColor(input, iGray, Imgproc.COLOR_BGR2GRAY);
        //Suavizado mediante filtro paso bajo (Gausian blur)
        Imgproc.blur(iGray, iGray, new Size(5,5));
        //Umbral adaptativo
        //Imgproc.adaptiveThreshold(src, dst, maxValue, adaptiveMethod, thresholdType, blockSize, C);
        Imgproc.adaptiveThreshold(iGray, iGray, 255, Imgproc.ADAPTIVE_THRESH_MEAN_C, Imgproc.THRESH_BINARY_INV, 15, 4);
        //ACCEDER A CADA PIXEL http://stackoverflow.com/questions/17035005/using-get-and-put-to-access-pixel-values-in-opencv-for-java
        Size inputSize = input.size(); //tamanyo de la captura
        output = input;
        int cont; //cuenta la cantidad de pixeles en blanco que hay dentro de cada cuadradito
        //La captura de divide en cuadraditos de tamanyo "tamanyo_cuadrado", cada cuadrado se trata por separado
        //int [] mapa_aux = new int[ (int)(cam_width/tamanyo_cuadrado) * (int)(cam_high/tamanyo_cuadrado)];


        for (int i = 0; i <(int)inputSize.height/tamanyo_cuadrado; i++) //recorro filas de la captura (Y)
            for (int j = 0; j < (int)inputSize.width/tamanyo_cuadrado; j++) { //recorro columnas de la captura (X)
                //OJO! (i=0, j=0) -> parte superior izquierda de la pantalla
                //(i=0, j=max) -> parte superior derecha de la pantalla
                // (i=max,j=max) -> parte inferior derecha de la pantalla

                cont=0; //reiniciar contador
                for (int x = 0; x < tamanyo_cuadrado; x++ ){ //recorro filas del cuadradito
                    for (int y = 0; y < tamanyo_cuadrado; y++ ){//recorro columnas del cuadradito

                        if(iGray.get(tamanyo_cuadrado*i+x,tamanyo_cuadrado*j+y)[0]>150)
                            //si el valor del pixel supera 150 (puede valer de 0 a 255), incremento contador
                            cont++;
                    }
                }
                if (cont>umbral) {

                    mapa[i * (int) (inputSize.width / tamanyo_cuadrado) + j] = 1;

                    for (int x = 0; x < tamanyo_cuadrado; x++ ){ //recorro filas del cuadradito
                        for (int y = 0; y < tamanyo_cuadrado; y++ ){//recorro columnas del cuadradito

                            if(cont>umbral) //si dentro del cuadradito el número de pixeles blancos supera el umbral
                                output.put(tamanyo_cuadrado*i+x,tamanyo_cuadrado*j+y, dataRed );//sobreescribo la captura
                        }
                    }
                }
                else
                    mapa[i*(int)(inputSize.width/tamanyo_cuadrado) + j]=0;

                //Log.d(TAG, "MAPA= "+ mapa[i*(int)(inputSize.width/tamanyo_cuadrado) + j]);
               /* for (int x = 0; x < tamanyo_cuadrado; x++ ){ //recorro filas del cuadradito
                    for (int y = 0; y < tamanyo_cuadrado; y++ ){//recorro columnas del cuadradito

                        if(cont>umbral) //si dentro del cuadradito el número de pixeles blancos supera el umbral
                            output.put(tamanyo_cuadrado*i+x,tamanyo_cuadrado*j+y, dataRed );//sobreescribo la captura
                    }
                }*/
            }
        //Log.d(TAG,"Resolucion"+cam_width+ "x"+cam_high);
        Imgproc.resize(output, output, new Size(cam_width,cam_high)); //Nos aseguramos de que estamos trabajando con la resolucion correcta
        return  output;
    }
}