package com.uva.rafael.tfg_goniometer.data.enums;


import android.content.ContentValues;

import com.uva.rafael.tfg_goniometer.R;
import com.uva.rafael.tfg_goniometer.data.Contract;

import xdroid.enumformat.EnumFormat;
import xdroid.enumformat.EnumString;

/**
 * Esta clase es una clase de tipo <tt>Enum</tt> que modela los posibles movimientos que puede
 * realizar una articulación.
 *
 * <p>Se encarga de proveer un método para insertar un "Tipo de Movimiento" en la Base de Datos,
 * pasando cada uno de los atributos que componen esta clase a un formato adecuado, por medio de un
 * objeto de tipo <tt>ContentValues</tt>.</p>
 *
 * <p>Como dato a señalar, los posibles valores de esta clase estan restringidos en función de la
 * articulación que se haya seleccionado en la clase enumerada ARTICULACION, de acuerdo con los
 * movimientos que puede realizar cada articulación; ademas, si se ha seleccionado el valor OTRO,
 * lo que se introduzca en el <tt>EditText</tt> se almacenara en <tt>otroTipoMovimiento</tt>.</p>
 *
 * <p>Por último, destacar que esta clase se encarga de proveer estos valores tanto en español como
 * en inglés.</p>
 *
 * <p>Esta clase forma parte de la aplicación TFG-Goniometer, desarrollada para el Trabajo de
 * Fin de Grado - Grado en Ingeniería Informatica (Universidad de Valladolid)</p>
 *
 * @author Rafael Matamoros Luque
 * @see com.uva.rafael.tfg_goniometer.data.Contract.MeasurementEntry
 * @version 1.0
 */
public enum TipoMovimiento {
    // Principales movimientos que pueden realizar las articulaciones
    @EnumString(R.string.flexion)
    FLEXION,
    @EnumString(R.string.extension)
    EXTENSION,
    @EnumString(R.string.aduccion)
    ADUCCION,
    @EnumString(R.string.abduccion)
    ABDUCCION,
    @EnumString(R.string.varo)
    VARO,
    @EnumString(R.string.valgo)
    VALGO,
    @EnumString(R.string.rotacion_interna)
    ROTACION_INTERNA,
    @EnumString(R.string.rotacion_externa)
    ROTACION_EXTERNA,
    @EnumString(R.string.pronacion)
    PRONACION,
    @EnumString(R.string.supinacion)
    SUPINACION,
    @EnumString(R.string.flexion_lateral)
    FLEXION_LATERAL,
    @EnumString(R.string.rotacion)
    ROTACION,
    @EnumString(R.string.otro)
    OTRO; // Este valor se utiliza para introducir un movimiento que no esté en esta lista

    // Texto introducido por el usuario cuando ha seleccionado el valor OTRO
    private String otroTipoMovimiento = "";

    /**
     * Método que se encarga de devolver el <tt>Enum</tt> asociado con el valor de tipo
     * <tt>String</tt> recibido como parámetro. En caso de que no encuentre ningún <tt>Enum</tt> que
     * se corresponda con este valor, lanza una excepción de tipo <tt>IllegalArgumentException</tt>,
     * emulando el comportamiento del método <tt>valueOf</tt>.
     *
     * @param value Valor a comparar con los valores de los distintos <tt>Enum</tt> de la clase
     * @return <tt>Enum</tt> asociado a ese valor
     */
    public static TipoMovimiento findByValue(String value) {
        for (TipoMovimiento tipoMovimiento : values()) {
            // Se compara el valor recibido como parámetro con los valores de cada uno de los Enum
            if (EnumFormat.getInstance().format(tipoMovimiento).equalsIgnoreCase(value))
                /*
                 * Para llevar a cabo esta tarea, se emplea el método "format" de la clase
                 * "EnumFormat", perteneciente a la biblioteca con el mismo nombre
                 */
                return tipoMovimiento;
        }
        /*
         * Si no se ha localizado ningún Enum que coincida con el valor recibido como parámetro,
         * se lanza una excepción
         */
        throw new IllegalArgumentException();
    }

    /**
     * "Constructor" de la clase, que se emplea cuando el usuario ha seleccionado el valor "OTRO" en
     * el Movimiento.
     *
     * @param otroTipoMovimiento Nombre del movimiento introducido por el usuario en el
     *                           <tt>EditText</tt>
     * @return Instancia de <tt>TipoMovimiento</tt> con el valor "OTRO" en <tt>tipoMovimiento</tt> y
     * el valor recibido como parámetro en <tt>otroTipoMovimiento</tt>.
     */
    public TipoMovimiento getOtroTipoMovimiento(String otroTipoMovimiento) {
        this.otroTipoMovimiento = otroTipoMovimiento;

        return this;
    }

    /**
     * Método que se encarga de dar un formato adecuado a cada uno de los atributos de la clase,
     * para, posteriormente, ser insertados en la Base de Datos.
     *
     * @param values <tt>ContentValues</tt>, recibido desde <tt>Medicion</tt>, al que añadir la
     *               información del <tt>TipoMovimiento</tt>
     */
    public void toContentValues(ContentValues values) {
        // Relacionar el campo de la tabla en la BD con el atributo que corresponde de la clase
        values.put(Contract.MeasurementEntry.MOVIMIENTO, this.toString());
        values.put(Contract.MeasurementEntry.OTRO_MOVIMIENTO, otroTipoMovimiento);
    }

    /**
     * Método <tt>toString()</tt> que se encarga de devolver el String con el valor seleccionado
     * por el usuario, al introducir una nueva medición.
     */
    @Override
    public String toString() {
        /*
         * Para llevar a cabo esta tarea, se emplea el método "format" de la clase "EnumFormat",
         * perteneciente a la biblioteca con el mismo nombre empleada para la i18n de los tipos Enum
         */
        return EnumFormat.getInstance().format(this);
    }
}
