<?php

/**
 * Class CompetitionModel . Clase CompetitionModel
 */
class CompetitionModel extends CI_Model


{
    const TABLE_NAME = 'Competicion';

    /**
     * CompetitionModel constructor.
     * Inicializa la base de datos
     */
    public function __construct()
    {
        parent::__construct();
        $this->load->database();
    }

    /**
     * Devuelve las competiciones que hay creadas en el Sistema
     * @param $perpage Numero de competiciones por pagina
     * @param $ofsset DEsplazamiento
     * @return mixed Competicion [] Con todos sus campos
     */
    public function getCompetitionsBy($perpage,$ofsset) {
       if($ofsset == null) {
           $sql = 'SELECT C.*,GE.descripcion as geDescripcion,TC.descripcion AS tcDescripcion
                FROM Competicion C , GrupoEdad GE ,TipoCompeticion TC 
                WHERE C.idGrupoEdad = GE.idGrupoEdad AND C.idTipoCompeticion = TC.idTipoCompeticion
                ORDER BY C.fecha DESC
                LIMIT ?';
           $query = $this->db->query($sql,array($perpage));
       }
       else {
           $sql = 'SELECT C.*,GE.descripcion as geDescripcion,TC.descripcion AS tcDescripcion
                FROM Competicion C , GrupoEdad GE ,TipoCompeticion TC 
                WHERE C.idGrupoEdad = GE.idGrupoEdad AND C.idTipoCompeticion = TC.idTipoCompeticion
                ORDER BY C.fecha DESC
                LIMIT ? OFFSET ?';
           $query = $this->db->query($sql,array($perpage,intval($ofsset)));
       }
       return $query -> result();
    }

    /**
     * Funcion que devuelve las competiciones que hay creadas en el Sistema
     * @return mixed Competicion [] Con todos sus campos
     */
    public function getAllCompetitions()
    {
        $sql = 'SELECT C.*,GE.descripcion as geDescripcion,TC.descripcion AS tcDescripcion
                FROM Competicion C , GrupoEdad GE ,TipoCompeticion TC 
                WHERE C.idGrupoEdad = GE.idGrupoEdad AND C.idTipoCompeticion = TC.idTipoCompeticion
                ORDER BY C.fecha DESC';
        $query = $this->db->query($sql);
        return $query->result();
    }

    /**
     * Funcion para crear una nueva competicion
     * @param $nombre Nombre de la competicion
     * @param $fecha Fecha en la que se va a desarrollar
     * @param $paisISOA3 Pais en  formato ISO A3
     * @param $autonomia Autonomia
     * @param $provincia Provincia
     * @param $pabellon Nombre del polideportivo
     * @param $emailDelegado Email del delegado
     * @param $grupoEdad Grupo de edad
     * @param $idTipoCompeticion Tipo de competicion
     * @param $numeroTatamis Numero de tatamis que tendra dicha competicion
     * @throws Exception Si existe algun tipo de error a la hora de crear
     */
    public function createCompetition($nombre, $fecha, $paisISOA3, $autonomia, $provincia, $pabellon, $emailDelegado,
                                      $grupoEdad, $idTipoCompeticion, $numeroTatamis)
    {
        $competition = array(
            'nombre' => $nombre,
            'fecha' => $fecha,
            'paisISOA3' => $paisISOA3,
            'autonomia' => $autonomia,
            'provincia' => $provincia,
            'pabellon' => $pabellon,
            'emailDelegado' => $emailDelegado,
            'idGrupoEdad' => $grupoEdad,
            'idTipoCompeticion' => $idTipoCompeticion
        );
        $this->db->trans_start();
        $this->db->insert(self::TABLE_NAME, $competition);
        $idCompeticion = $this->db->insert_id(); // returns the latest id create by mysqli

        for ($i = 0; $i < $numeroTatamis; $i++) {
            $tatami = array(
                'numero' => $i + 1,
                'idCompeticion' => $idCompeticion
            );

            $this->db->insert('Tatami', $tatami);
        }
        $this->db->trans_complete();
        if (!$this->db->trans_status()) throw new Exception('Error, no se pudo crear la competicion');
    }

    /**
     * Funcion para obtener los tatamis de una determinada competicion
     * @param $idCompetition Identificador de la competicion de la cual se obtienen sus tatamis
     * @return mixed Tatami [] con sus campos
     * @throws Exception Si existe error
     */
    public function getMatsByCompetitionId($idCompetition)
    {
        $this->db->trans_start();
        $sql = 'SELECT T.* FROM Tatami T WHERE T.idCompeticion = ?';
        $query = $this->db->query($sql, array($idCompetition));
        $this->db->trans_complete();
        if (!$this->db->trans_status()) {
            throw new Exception('Error, no se pudieron obtener los tatamis');
        } else {
            return $query->result();
        }

    }

    /**
     * Retorna una c ompeticion obteniendola a traves de su identificador principal
     * @param $id Identificador de la competicion
     * @return mixed Competicion [] con todos sus campos
     * @throws Exception Si existe error a la hora de procesar la transaccion
     */
    public function getCompetition($id)
    {

        $sql = 'SELECT C.*,GE.descripcion as geDescripcion,TC.descripcion AS tcDescripcion
                FROM Competicion C , GrupoEdad GE ,TipoCompeticion TC 
                WHERE C.idGrupoEdad = GE.idGrupoEdad AND C.idTipoCompeticion = TC.idTipoCompeticion AND C.idCompeticion = ?';
        $this->db->trans_start();
        $query = $this->db->query($sql, array($id));
        $this->db->trans_complete();
        if (!$this->db->trans_status()) {
            throw new Exception('Error, no se pudo obtener la competicion');
        } else {
            return $query->row();
        }
    }

    /**
     * Funcion que elimina una competicion con identificador @id pasado por parametro
     * @param $id Identificador de la competicion que se quiere eliminar
     * @throws Exception si existe erro a la hora de procesar la transaccion
     */
    public function deleteCompetition($id)
    {
        $competition_date = $this -> getCompetition($id) -> fecha;
        $idWeights = $this ->peso_to_array($this -> get_idWeights( $this -> getCompetition($id) -> idGrupoEdad));
        $this->db->where('idCompeticion', $id);
        $this->db->trans_start();
        $this->db->delete(self::TABLE_NAME);
        $this->db->trans_complete();
        if (!$this->db->trans_status()) {
            throw new Exception('Error, it was impossible delete that compoetition');
        }

        $this -> db -> where ('fecha_participacion',$competition_date);
        // new
        $this -> db -> where_in ('idPeso',$idWeights);

        //
        $this->db->trans_start();
        $this->db->delete('Participacion');
        $this->db->trans_complete();
        if (!$this->db->trans_status()) {
            throw new Exception('Error, it was impossible delete that compoetition');
        }
        $this->db->trans_start();
        $this -> db -> where ('idCompeticion',$id);
        $this -> db -> delete('Tatami');
        $this->db->trans_complete();
        if (!$this->db->trans_status()) {
            throw new Exception('Error, impossible to delete mats');
        }



    }
    private function get_idWeights($idAgeGroup) {
        $sql = 'SELECT P.idPeso FROM Peso P WHERE P.idGrupoEdad = ?';
        $query = $this->db->query($sql,array($idAgeGroup));
        return $query->result();
    }

    private function peso_to_array($array) {
        $a = array();
        foreach ($array as $b) {
            $a[] = $b-> idPeso;
        }
        return $a;
}

    /**
     * Funcion que inscribe a un arbitro en una competicion
     * @param $id identificador de la competicion
     * @param $dni identificador del arbitro
     * @param $nombreEquipo nombre del equipo
     * @throws Exception Si existe error a la hora de procesar la transaccion
     */
    public function addRefereeToCompetition($id, $dni, $nombreEquipo)
    {
        $current_date = date('
        Y-m-d');
        $inscription = array(
            'idCompeticion' => $id,
            'dniPersona' => $dni,
            'fecha_inscripcion' => $current_date,
            'nombreEquipo' => $nombreEquipo,
            'arbitra' => 1
        );
        $this->db->trans_start();
        $this->db->insert('Inscripcion', $inscription);
        $this->db->trans_complete();
        if (!$this->db->trans_status()) throw new Exception('Error, no se pudo crear la inscripcion');

    }

    /**
     * Eliminar la inscripción de un determinado árbitro de una determinada competicion
     * valores pasados por parametros
     * @param $idCompeticion Identificador de la competicion
     * @param $dni Identificador del arbitro
     * @throws Exception Si existe error a la hora de procesar la transaccion
     */
    public function deleteRefereeInscription($idCompeticion, $dni)
    {
        $this->db->trans_start();
        $this->db->where('idCompeticion', $idCompeticion);
        $this->db->where('dniPersona', $dni);
        $this->db->delete('Inscripcion');
        $mats = $this->getMatsByCompetitionId($idCompeticion);
        foreach ($mats as $mat) {
            if ($this->exists($mat->idTatami, $dni)) $this->deleteRefereeToMat($mat->idTatami, $dni);
        }
        $this->db->trans_complete();
        if (!$this->db->trans_status()) {
            throw new Exception('Error, iit was impossible to delete the referee inscription');
        }
    }

    /**
     * Devuelve los arbitros inscritos en la competicion
     * @param $id competicion
     * @return Persona [] con sus campos
     */
    public function getRefereesRolleIn($id)
    {
        $sql = 'SELECT A.*, C.descripcion, E.nombre AS nombreEquipo
                FROM Persona A, Inscripcion I, CategoriaArbitral C, Equipo E
                WHERE I.idCompeticion = ? AND I.dniPersona = A.dni and I.arbitra = 1 AND A.idCategoriaArbitral = C.idCategoriaArbitral AND E.nombre = I.nombreEquipo';
        $this->db->trans_start();
        $query = $this->db->query($sql, array($id));
        $this->db->trans_complete();
        if (!$this->db->trans_status()) {
            throw new Exception('');
        } else {
            return $query->result();
        }
    }

    /**
     * Cuando no hay ningun competidor inscrito -> devuelve null
     * Arbitros que no esten inscritos en la competicion cuyo id es pasado por parametro
     * @param $id
     * @return mixed
     * @throws Exception
     */
    public function getRefereesNotRolleIn($id)
    {
        $sql = 'SELECT DISTINCT A.*,C.descripcion
                FROM Persona A, Inscripcion I,CategoriaArbitral C
                WHERE A.idCategoriaArbitral = C.idCategoriaArbitral AND  I.idCompeticion = ? AND A.dni NOT IN (SELECT I.dniPersona 
                                                                                                              FROM Persona A, Inscripcion I
                                                                                                              WHERE I.idCompeticion = ? AND I.dniPersona = A.dni)';
        $this->db->trans_start();

        $query = $this->db->query($sql, array($id, $id));
        $this->db->trans_complete();
        if (!$this->db->trans_status()) {
            throw new Exception('');
        } else {
            return $query->result();
        }
    }

    /**
     * Añade un arbitro a un tatami
     * @param $idMat Identificador del tatami
     * @param $dni Identificador del arbitro
     */
    public function addRefereeToMat($idMat, $dni, $idCompetition)
    {
        $matToReferee = array(
            'idTatami' => $idMat,
            'dniArbitro' => $dni
        );

        $mats = $this->getMatsByCompetitionId($idCompetition);
        foreach ($mats as $mat) {
            if ($this->exists($mat->idTatami, $dni)) $this->deleteRefereeToMat($mat->idTatami, $dni);
        }
        $this->db->insert('ArbitroATatami', $matToReferee);

    }

    /**
     * Arbitros asociados a un determinado tatami
     * @param $idMat Identificador del tatami
     * @throws Exception Si existe error a la hora de procesar la transaccion
     */
    public function getReferees($idMat)
    {
        $sql = 'SELECT A.*, CA.descripcion 
                    FROM Persona A, CategoriaArbitral CA , ArbitroATatami AT
                    WHERE AT.idTatami = ? AND AT.dniArbitro = A.dni AND CA.idCategoriaArbitral = A.idCategoriaArbitral';

        $this->db->trans_start();
        $query = $this->db->query($sql, array($idMat));
        $this->db->trans_complete();
        if (!$this->db->trans_status()) {
            throw new Exception('');
        } else {
            return $query->result();
        }
    }

    /**
     * Funcion que devuelve los arbitros que no estan ascociados a ningun tatatami en la competicion que es pasada por parametro
     * @param $idCompetition Identificador de la competicion
     * @return mixed Persona [] Arbitros que no estan inscritos
     * @throws Exception Si existe error a la hora de procesar la transaccion
     */
    public function getRefereesNotAssociateToMat($idCompetition)
    {
        $sql = 'select A.*,CA.descripcion 
                from persona A, categoriaarbitral CA
                where A.idCategoriaArbitral = CA.idCategoriaArbitral and
                A.dni in (select I.dniPersona from inscripcion I where I.idCompeticion = ? and I.arbitra = 1) and
                A.dni not in (select R.dniArbitro from arbitroatatami R where R.idTatami = any (select T.idTatami from tatami T where T.idCompeticion = ?)) ';

        $this->db->trans_start();
        $query = $this->db->query($sql, array($idCompetition, $idCompetition));
        $this->db->trans_complete();
        if (!$this->db->trans_status()) {
            throw new Exception('');
        } else {
            return $query->result();
        }

    }


    /**
     * Funcion que devuelve los pesos en funcion de la competicion
     * @param $id Identificador de la competicion
     * @param $sex Sexo del que se quieren obtener los pesos
     * @return mixed Peso [] con sus campos
     */
    public function getWeigths($id, $sex)
    {
        $sql = 'SELECT P.* 
                FROM Peso P,Competicion C, GrupoEdad GE
                 WHERE C.idCompeticion = ? AND C.idGrupoEdad = GE.idGrupoEdad AND GE.idGrupoEdad = P.idGrupoEdad AND P.sexo = ?';
        $query = $this->db->query($sql, array($id, $sex));
        return $query->result();

    }

    /**
     * Competidores que esten inscritros en una competicion cuyo parametro
     * es pasado como parametro
     * @param $id de la competicion
     */
    public function getCompetitorsEnroll($id)
    {
        $sql = 'SELECT  A.*, C.descripcion, E.nombre AS nombreEquipo
                FROM Persona A, Inscripcion I, CategoriaArbitral C, Equipo E
                WHERE I.idCompeticion = ? AND I.dniPersona = A.dni and I.arbitra = 0 AND A.idCategoriaArbitral = C.idCategoriaArbitral AND E.nombre = I.nombreEquipo';
        $this->db->trans_start();
        $query = $this->db->query($sql, array($id));
        $this->db->trans_complete();
        if (!$this->db->trans_status()) {
            throw new Exception('');
        } else {
            return $query->result();
        }
    }


    private function exists($idMat, $dni)
    {
        $sql = 'SELECT * 
                FROM ArbitroATatami AT 
                WHERE AT.idtatami = ? AND AT.dniArbitro = ? ';
        $query = $this->db->query($sql, array($idMat, $dni));

        return $query->num_rows() != 0;
    }

    private function deleteRefereeToMat($idMat, $dni)
    {
        $this->db->where('idTatami', $idMat);
        $this->db->where('dniArbitro', $dni);
        $this->db->delete('ArbitroATatami');
    }

    /**
     * Funcion que indica si existe una competicion en una fecha y grupo de edad
     * @param $date Fecha de la competicion
     * @param $ageGroup Grupo de edad
     * @return bool true si existe la competicion false en caso contrario
     */
    public function existsCompetition($date, $ageGroup)
    {
        $sql = 'SELECT * 
                FROM Competicion C 
                WHERE C.fecha = ? AND C.idGrupoEdad = ?';
        $query = $this->db->query($sql, array($date, $ageGroup));

        return $query->num_rows() != 0;
    }

    /**
     * Funcion que indica si existe una inscripcion de una persona (Arbitro | Competidor)
     * @param $dni dni de la persona (Arbitro |Competidor)
     * @param $idCompetition Identificador de la competicion
     * @return bool true si existe false en caso contrario
     */
    public function existsInscription($dni, $idCompetition)
    {
        $sql = 'SELECT I.* FROM Inscripcion I WHERE I.dniPersona = ? AND I.idCompeticion = ?';
        $query = $this->db->query($sql, array($dni, $idCompetition));

        return $query->num_rows() != 0;

    }

    /**
     * Funcion que devuelve los competidores con la posicion en una determinada competicion y peso
     * @param $idCompetition Identificador de la competicion
     * @param $idWeight Identificador de peso
     * @return mixed Persona [] con sus campos, puesto entre ellos
     */
    public function getCompetitorsWithPosition($idCompetition,$idWeight){
        $sql = 'SELECT P.*, I.nombreEquipo,PA.puesto
                FROM Persona P, Inscripcion I, Participacion PA,Competicion C
                WHERE P.dni = I.dniPersona AND PA.dniCompetidor = I.dniPersona AND I.idCompeticion = ? AND PA.idPeso = ?
                AND C.idCompeticion = I.idCompeticion AND C.fecha = PA.fecha_participacion';

        $query = $this -> db -> query($sql,array($idCompetition,$idWeight));
        return $query -> result();
    }


}