package com.uva.rafael.tfg_goniometer.presenter;

import android.app.Fragment;
import android.content.DialogInterface;
import android.content.pm.ActivityInfo;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;

import com.uva.rafael.tfg_goniometer.R;
import com.uva.rafael.tfg_goniometer.interfaces.PresenterFunctions;
import com.uva.rafael.tfg_goniometer.model.MainModel;
import com.uva.rafael.tfg_goniometer.view.MainActivity;
import com.uva.rafael.tfg_goniometer.view.adapters.MedicionListAdapter;
import com.uva.rafael.tfg_goniometer.view.fragments.UltimasMedicionesFragment;

/**
 * Este es el Presentador asociado al <tt>Fragment UltimasMedicionesFragment</tt> de la aplicación.
 * Se encarga de llevar a cabo toda la lógica asociada a las acciones del usuario realizadas en la IU.
 *
 * <p>En concreto, se encarga de realizar la "configuración inicial" del <tt>Fragment</tt>, que,
 * consiste en actualizar el item del <tt>NavigationView</tt> al tercer ítem del mismo, fijar la
 * orientación de la pantalla a "Portrait", para evitar que se pueda girar y fijar el <tt>Toolbar</tt>
 * como <tt>SupportActionBar</tt>.</p>
 *
 * <p>Además de eso, se encarga de configurar el <tt>RecyclerView</tt> inicial que se emplea para
 * mostrar el listado de las últimas 10 mediciones almacenadas en la Base de Datos(obteniendo el
 * <tt>RecyclerView.Adapter</tt>).</p>
 *
 * <p>Por último, se encarga de obtener el <tt>RecyclerView.Adapter</tt> actualizado cada
 * vez que se borra una de las mediciones de la Base de Datos.</p>
 *
 * <p>Esta clase forma parte de la aplicación TFG-Goniometer, desarrollada para el Trabajo de
 * Fin de Grado - Grado en Ingeniería Informática (Universidad de Valladolid)</p>
 *
 * @author Rafael Matamoros Luque
 * @see UltimasMedicionesFragment
 * @see MainModel
 * @see Toolbar
 * @see AlertDialog
 * @version 1.0
 */
public class UltimasMedicionesPresenter implements PresenterFunctions,
        PresenterFunctions.UltimasMedicionesFunctions {

    private final MainModel model;
    // Referencias al fragmento (Vista) con el que está asociado y al Modelo de la aplicación
    private UltimasMedicionesFragment fragment;

    /**
     * Constructor principal de la clase
     *
     * @param fragment Fragmento (Vista) con la que mantiene una relación 1-a-1.
     * @param model    Modelo (único) de la aplicación.
     */
    public UltimasMedicionesPresenter(Fragment fragment, MainModel model) {
        this.fragment = (UltimasMedicionesFragment) fragment;
        this.model = model;
    }

    /**
     * Método que realiza las operaciones iniciales cuando se crea el
     * <tt>Fragment UltimasMedicionesFragment</tt>.
     * <p>
     * <p>Se encarga de marcar el tercer ítem del <tt>NavigationView</tt> (correspondiente a
     * <tt>UltimasMedicionesFragment</tt>), fijar la orientación de la pantalla en "Portrait" y de
     * utilizar el <tt>Toolbar</tt> recibido como <tt>SupportActionBar</tt>.</p>
     *
     * @param toolbar <tt>Toolbar</tt> a emplear como <tt>SupportActionBar</tt>
     */
    @Override
    public void setUpInitialSettings(Toolbar toolbar) {
        // Marcar el tercer ítem del Navigationview
        ((MainActivity) fragment.getActivity()).setNavigationItem(2);

        // Fijar la orientación de la pantalla en "Portrait"
        fragment.getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

        // Utilizar el toolbar como SupportActionBar
        AppCompatActivity activity = ((AppCompatActivity) fragment.getActivity());

        activity.setSupportActionBar(toolbar);

        if (activity.getSupportActionBar() != null)
            activity.getSupportActionBar().setHomeAsUpIndicator(R.mipmap.ic_menu);

        activity.getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        activity.getSupportActionBar().setTitle("");
    }

    /**
     * Método que se encarga de hacer una configuración inicial del <tt>RecyclerView</tt> que muestra
     * el listado de las últimas 10 mediciones almacenadas en la Base de Datos.
     *
     * <p>Realiza una operación para mejorar el rendimiento del mismo, así como añadirle el
     * <tt>LayoutManager</tt> y el <tt>RecyclerView.Adapter</tt>.</p>
     *
     * @param recyclerView <tt>RecyclerView</tt> a configurar
     */
    @Override
    public void configRecyclerView(RecyclerView recyclerView) {
        // Operación para mejorar el rendimiento del RecyclerView
        recyclerView.setHasFixedSize(true);

        // Obtención del LayoutManager a partir de la actividad principal
        RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(fragment.getActivity());
        recyclerView.setLayoutManager(layoutManager);

        // Obtención del adaptador (MedicionListAdapter)
        RecyclerView.Adapter adapter = getUltimasMediciones();
        recyclerView.setAdapter(adapter);
    }

    /*
     * Método que se encarga de devolver una instancia de RecyclerView.Adapter (MedicionListAdapter
     * en este caso)
     */
    private MedicionListAdapter getUltimasMediciones() {
        return new MedicionListAdapter(model.getUltimasMediciones(), this);
    }

    /**
     * Evento <tt>ClickListener</tt> que se llama cuando el usuario ha pulsado sobre el botón para
     * borrar la medición en <tt>UltimasMedicionesFragment</tt>.
     *
     * <p>Se encarga de crear un diálogo que envía a la Vista para que se lo muestre al usuario, con
     * el fin de confirmar que quiere borrar la medición seleccionada.</p>
     *
     * <p>Si el usuario confirma que desea eliminar la medición, el método se encarga de mostrar el
     * listado de las últimas 10 mediciones almacenadas, actualizado con la medición ya eliminada.</p>
     *
     * @param nombre Nombre del paciente al que se le realizó la medición
     * @param fechaHora Fecha y hora en la que se realizó la medición
     */
    @Override
    public void onDeleteMeasurementClicked(String nombre, final String fechaHora) {
        // Diálogo que se mostrará al usuario
        AlertDialog dialog;

        // 1. Instantiate an AlertDialog.Builder with its constructor
        AlertDialog.Builder builder = new AlertDialog.Builder(fragment.getActivity());

        // 2. Chain together various setter methods to set the dialog characteristics
        builder.setTitle(nombre);
        builder.setMessage(R.string.confirmacion_borrado_medicion);

        // 3. Add the buttons
        builder.setPositiveButton(R.string.eliminar, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                // User clicked ELIMINAR button

                /*
                 * Se intenta eliminar la medición de la BD a través del Modelo, pasando la fecha
                 * y hora a un formato reconocido por la BD
                 */
                if (model.onDeleteMeasurement(fechaHora.replace("\n", " ")) == 1) {
                    /*
                     * La medición se ha podido eliminar con éxito. Notificar a la vista que
                     * muestre un mensaje indicando esta situación al usuario
                     */
                    fragment.displaySuccess();

                    /*
                     * Se re-asigna el RecyclerView.Adapter con el listado de las últimas 10
                     * mediciones actualizado, habiendo eliminado ya esta medición
                     */
                    fragment.setAdapter(getUltimasMediciones());
                }
                else
                    /*
                     * Se ha producido un error al eliminar la medición de la BD. Notificar a la
                     * Vista para que informe de esta situación al usuario
                     */
                    fragment.displayError();
            }
        });

        builder.setNegativeButton(R.string.cancelar, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                // User clicked CANCELAR button

                // No realizar ninguna acción. Simplemente cerrar el diálogo
            }
        });

        // 4. Get the AlertDialog from create()
        dialog = builder.create();

        // Enviar el diálogo a la Vista para que se lo muestre al usuario
        fragment.displayResult(dialog);
    }

    /**
     * Perform any final cleanup before an activity is destroyed.
     *
     * Se encarga de liberar la referencia al <tt>Fragment</tt> con el que está asociado.
     */
    @Override
    public void onDestroy() {
        fragment = null;
    }
}
