package com.uva.rafael.tfg_goniometer.view.fragments;

import android.app.Fragment;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.RelativeLayout;
import android.widget.Spinner;

import com.uva.rafael.tfg_goniometer.R;
import com.uva.rafael.tfg_goniometer.dependencyInjection.App;
import com.uva.rafael.tfg_goniometer.presenter.PacientesPresenter;

import javax.inject.Inject;

/**
 * Esta clase es el <tt>Fragment</tt> que se encarga de mostrar el listado de pacientes que se
 * encuentran almacenados en la Base de Datos, y acceder al perfil de cada uno de ellos pulsando
 * sobre su nombre.
 *
 * <p>Además, permite hacer un filtrado de este listado de pacientes en tiempo real (según va
 * introduciendo caracteres el usuario) en función del criterio de búsqueda seleccionado en el
 * <tt>Spinner</tt> (Nombre, ID o Tags) y de la información introducida en el <tt>EditText</tt>.</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 PacientesPresenter
 * @see TextWatcher
 * @see Spinner
 * @see Toolbar
 * @see RecyclerView
 * @version 1.0
 */
public class PacientesFragment extends Fragment implements TextWatcher {

    /*
     * Presentador asociado con este Fragment (Vista). Su instancia se obtiene mediante Inversión
     * de Dependencias
     */
    @SuppressWarnings({"unused", "CanBeFinal"})
    @Inject
    PacientesPresenter presenter;

    /*
     * Variables que se utilizan en conjunción para realizar el filtrado de pacientes.
     *
     * El Spinner indica el criterio de filtrado (Nombre, ID, o Tags), y el EditText el filtro en sí.
     */
    private Spinner spinner;
    private EditText busqueda;

    // RecyclerView que se emplea para mostrar el listado de pacientes
    private RecyclerView recyclerView;

    /**
     * Método llamado para instanciar el <tt>Fragment</tt> con su layout asociada
     * (R.layout.pacientes_fragment, en este caso). Además de eso, se encarga de notificar a
     * <tt>PacientesPresenter</tt> cuando el usuario pulsa sobre uno de los elementos del
     * <tt>RecyclerView</tt>, o cuando pulsa sobre el botón para añadir un nuevo paciente en la Base
     * de Datos.
     *
     * @param inflater The LayoutInflater object that can be used to inflate any view in the
     *                 fragment.
     * @param container If non-null, this is the parent view that the fragment's UI should be
     *                  attached to. The fragment should not add the view itself, but this can be
     *                  used to generate the LayoutParams of the view.
     * @param savedInstanceState If non-null, this fragment is being re-constructed from a previous
     *                           saved state as given here. Return the View for the fragment's UI,
     *                           or null.
     */
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {

        // Obtención de la instancia de PacientesPresenter
        ((App) getActivity().getApplication()).getComponent(this).injectPacientesFragment(this);

        // Inflar el layout del Fragment
        View vista = inflater.inflate(R.layout.pacientes_fragment, container, false);

        // Bindeo del Toolbar
        Toolbar toolbar = (Toolbar) vista.findViewById(R.id.toolbar);

        // Configuración inicial
        presenter.setUpInitialSettings(toolbar);

        // Bindeo del EditText donde el usuario introducirá los carácteres de filtrado de pacientes
        busqueda = ((EditText) vista.findViewById(R.id.patientSearch));
        // Además, se le añade un TextChangedListener para saber cuándo escribe el usuario
        busqueda.addTextChangedListener(this);

        // Bindeo del Spinner que contiene los criterios de filtrado de pacientes
        spinner = (Spinner) vista.findViewById(R.id.spinner);
        // Carga del Spinner con los elementos "Nombre", "ID", "Tags"
        presenter.loadSpinner(spinner);

        /*
         * Bindeo del RelativeLayout que contiene al Spinner y a la imagen de la flecha que lo
         * acompaña, para que el usuario pueda pulsar sobre la flecha y se despliegue el "dropdown"
         * del Spinner también.
         */
        RelativeLayout spinner_dropdown = (RelativeLayout) vista.findViewById(R.id.spinner_dropdown);
        spinner_dropdown.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                spinner.performClick();
            }
        });

        /*
         * Bindeo del RecyclerView donde se muestra el listado de pacientes almacenados, y
         * configuración del mismo
         */
        recyclerView = (RecyclerView) vista.findViewById(R.id.recyler_view);
        presenter.configRecyclerView(recyclerView, getArguments());

        // Bindeo del FloatingActionButton para añadir un nuevo paciente
        final FloatingActionButton añadirPaciente = (FloatingActionButton) vista.findViewById(R.id.añadir_paciente);
        añadirPaciente.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // Notificar a PacientesPresenter cuando se pulse este botón
                presenter.onAñadirPacienteClicked();
            }
        });
        return vista;
    }

    /**
     * This method is called to notify you that, within 'charSequence', the 'count' characters
     * beginning at 'start' are about to be replaced by new text with length 'after'.
     *
     * @param charSequence CharSequence
     * @param start        int
     * @param count        int
     * @param after        int
     */
    @Override
    public void beforeTextChanged(CharSequence charSequence, int start, int count, int after) {
        // No se necesita esta funcionalidad
    }

    /**
     * This method is called to notify you that, within 'charSequence', the 'count' characters
     * beginning at 'start' have just replaced old text that had length 'before'.
     *
     * Además, se encarga de notificar a <tt>PacientesPresenter</tt> que el usuario ha introducido
     * un carácter, para que actualice el adaptador del <tt>RecyclerView</tt> teniendo en cuenta la
     * información que acaba de introducir el usuario en el <tt>EditText</tt> y el criterio de
     * filtrado seleccionado en el <tt>Spinner</tt>.
     *
     * @param charSequence CharSequence
     * @param start int
     * @param before int
     * @param count int
     */
    @Override
    public void onTextChanged(CharSequence charSequence, int start, int before, int count) {
        presenter.onTextChanged(recyclerView, busqueda.getText().toString(),
                spinner.getSelectedItem().toString(), getArguments());
    }

    /**
     * This method is called to notify you that, somewhere within 's', the text has been changed.
     *
     * @param s Editable
     */
    @Override
    public void afterTextChanged(Editable s) {
        // No se necesita esta funcionalidad
    }

    /**
     * Perform any final cleanup before an activity is destroyed.
     */
    @Override
    public void onDestroy() {
        presenter.onDestroy();
        super.onDestroy();
    }
}
