<?php
class UtilisateurGateway
{
    private Connection $con;

    /**
     * @param Connection $con
     */
    public function __construct(){
        global $dsn, $rep, $vues, $error;
        try{
        $con = new Connection($dsn);
        $this->con = $con;
        } catch (Exception $e) {
            $error = $e->getMessage();
            require($rep . $vues['erreur']);
        }
    }

    /**
     * @param Connection $con
     */
    public function setCon(Connection $con): void
    {
        $this->con = $con;
    }

    public function insert(Utilisateur $utilisateur) : void{
        $query = "INSERT INTO Utilisateur VALUES (:email,:pseudo,:mdp,:estAdmin)";
        $this->con->executeQuery($query,	array(
            ':email'	=>	array($utilisateur->getEmail(),SQLITE3_TEXT),
            ':pseudo'	=>	array($utilisateur->getPseudo(),SQLITE3_TEXT),
            ':mdp'	=>	array($utilisateur->getMdp(),SQLITE3_TEXT),
            ':estAdmin'	=>	array($utilisateur->getEstAdmin(),SQLITE3_INTEGER)));
    }

    public function delete(string $email) : void{
        $query = "DELETE FROM utilisateur WHERE email=:email";
        $this->con->executeQuery($query,	array(
            ':email'	=>	array($email ,SQLITE3_TEXT)
        ));
    }

    public function getUtilisateurByEmail(string $email) : Utilisateur{
        global $error;
        $query = "SELECT * FROM Utilisateur WHERE email=:email";
        $this->con->executeQuery($query,	array(
            ':email'	=>	array($email,SQLITE3_TEXT)
        ));
        $results=$this->con->getResults();
        return UtilisateurFactory::createUtilisateur($results);
    }

    public function getMdpByEmail(string $email) : string{
        global $error;
        $query = "SELECT mdp FROM Utilisateur WHERE email=:email";
        $this->con->executeQuery($query,	array(
            ':email'	=>	array($email,SQLITE3_TEXT)
        ));
        $results=$this->con->getResults();
        foreach ($results as $row) {
            $mdp=$row['mdp'];
        }
        if ($results == null){
            $error = "Mot de passe non trouvé.";
            throw new Exception("Mots de passe Incorrect");
        }
        return $mdp;
    }
    public function getPseudoByEmail(string $email) : string{
        global $error;
        $query = "SELECT pseudo FROM Utilisateur WHERE email=:email";
        $this->con->executeQuery($query,	array(
            ':email'	=>	array($email,SQLITE3_TEXT)
        ));
        $results=$this->con->getResults();
        foreach ($results as $row) {
            $pseudo=$row['pseudo'];
        }
        if ($results == null){
            $error = "Pseudo non trouvé.";
            throw new Exception("Pseudo Incorrect");
        }
        return $pseudo;
    }

    public function getEstAdminByEmail(string $email) : bool{
        $query = "SELECT estAdmin FROM Utilisateur WHERE email=:email";
        $this->con->executeQuery($query,	array(
            ':email'	=>	array($email,SQLITE3_TEXT)
        ));
        $results=$this->con->getResults();
        $estAdmin=$results[0]['estAdmin'];
        return $estAdmin;
    }

    public function addToQueue(Utilisateur $utilisateur,Partie $partie){
        $query = "INSERT INTO Participer VALUES (:idPartie,:idUtilisateur,0)";
        $this->con->executeQuery($query,array(
            ':idUtilisateur' => array($utilisateur->getEmail(),SQLITE3_TEXT),
            ':idPartie' => array($partie->getIdPartie(), SQLITE3_INTEGER)
        ));
    }

    public function findUsersInQueue() : array{
        $query = "SELECT u.* FROM Utilisateur u, Participer p
        WHERE u.email=p.utilisateur
        AND p.etat=0";
        $this->con->executeQuery($query);
        $results = $this->con->getResults();
        $user_group = UtilisateurFactory::createTabUtilisateur($results);
        return $user_group;
    }

    public function isAlreadyInqueue(Utilisateur $utilisateur) : bool{
        $query="SELECT utilisateur FROM Participer WHERE utilisateur=:utilisateur";
        $this->con->executeQuery($query, array(
            ':utilisateur' => array($utilisateur->getEmail(),SQLITE3_TEXT)
        )
        );
        $results=$this->con->getResults();
        if (empty($results))
            return false;
        else
            return true;
    }

    public function queueFilled(){
        $query = "SELECT count(*) FROM Participer WHERE etat=0";
        $this->con->executeQuery($query);
        if ($this->con->getResults()[0]['count(*)'] >= 2)
            return True;
        else
            return False;
    }

    public function passerEnigmeMulti(string $emailUtilisateur){
        $query="SELECT p.partie FROM Participer
        WHERE p.utilisateur = :emailUtilisateur
        and p.enCours = TRUE";
        $this->con->executeQuery($query,    array(
            ':emailUtilisateur' =>    array($emailUtilisateur,SQLITE3_TEXT)
        ));
        $idPartie=$this->con->getResults()[0]["partie"];

        $query="SELECT e.id, c2.indexEnigme FROM Resoudre r, Contenir c1,Contenir c2, Enigme e WHERE
        r.id = :idPartie
        AND r.utilisateur=:idUtilisateur
        AND r.partie=:idPartie
        AND r.temps IS NOT NULL
        AND r.enigme=c1.enigme
        AND r.partie = c1.partie
        AND r.partie = c2.partie
        AND c2.index=c1.index + 1
        AND e.id = c1.enigme
        AND r.temps = (SELECT max(r.temps))";
        $results=$this->con->getResults();
        if(empty($results))
            $query="SELECT c.enigme, c.indexEnigme FROM Contenir c WHERE
            c.partie = :idPartie
            AND c.indexEnigme = 0";
            $results=$this->con->getResults();
        $idEnigme=$results[0]["enigme"];
        $index=$results[0]["indexEnigme"];

        $query="INSERT INTO Resoudre VALUES (:utilisateur, :enigme,:partie,:classement,:index,:temps,TRUE)";
        $this->con->executeQuery($query, array(
            "utilisateur" => array($emailUtilisateur, SQLITE3_TEXT),
            "enigme" => array($idEnigme, SQLITE3_INTEGER),
            "partie" => array($idPartie, SQLITE3_INTEGER),
            "classement" => array(NULL, SQLITE3_NULL),
            "index" => array($index, SQLITE3_INTEGER),
            "temps" => array($emailUtilisateur, SQLITE3_FLOAT)));
    }

    public function resoudreEnigmeSolo(string $emailUtilisateur)
    {
        $query="SELECT c.partie FROM Contenir
        WHERE c.utilisateur = :emailUtilisateur
        and c.enCours = TRUE";
        $this->con->executeQuery($query,    array(
            ':emailUtilisateur' =>    array($emailUtilisateur,SQLITE3_TEXT)
        ));
        $idPartie=$this->con->getResults()[0]["partie"];

        $query="SELECT e.id, c2.indexEnigme FROM Resoudre r, Contenir c1,Contenir c2, Enigme e WHERE
        r.id = :idPartie
        AND r.utilisateur=:idUtilisateur
        AND r.partie=:idPartie
        AND r.enigme = c1.enigme
        AND c1.partie = r.partie
        AND c2.partie = r.partie
        AND c2.index=c1.index + 1
        AND e.id = c2.enigme
        AND r.indexEnigme = (SELECT max(r.indexEnigme))";
        $results=$this->con->getResults();
        if(empty($results))
        {
            $query="SELECT c.enigme, c.indexEnigme FROM Contenir c WHERE
            c.partie = :idPartie
            AND c.indexEnigme = 0";
            $results=$this->con->getResults();
        }
        $idEnigme=$results[0]["enigme"];
        $index=$results[0]["indexEnigme"];

        $query="SELECT max(classement) FROM Enigme e,Partie p, Resoudre r
        WHERE p.id=r.partie
        AND e.id=r.enigme";
        $this->con->executeQuery($query);
        $results=$this->con->getResults();
        if(empty($results))
            $classement=1;
        else
            $classement=$results[0]["max"]+1;

        $query="SELECT * FROM Resoudre
        WHERE r.utilisateur=:utilisateur
        AND r.enigme=:idEnigme
        AND r.partie=:idPartie";
        $this->con->executeQuery($query, array(
        "utilisateur" => array($emailUtilisateur, SQLITE3_TEXT),
        "enigme" => array($idEnigme, SQLITE3_INTEGER),
        "partie" => array($idPartie, SQLITE3_INTEGER)));
        $results=$this->con->getResults();
        if(empty($results))
        {
            $query="INSERT INTO Resoudre VALUES (:utilisateur, :enigme,:partie,:classement,:index,:temps,TRUE)";
            $this->con->executeQuery($query, array(
                "utilisateur" => array($emailUtilisateur, SQLITE3_TEXT),
                "enigme" => array($idEnigme, SQLITE3_INTEGER),
                "partie" => array($idPartie, SQLITE3_INTEGER),
                "classement" => array($classement, SQLITE3_INTEGER),
                "index" => array($index, SQLITE3_INTEGER),
                "temps" => array($emailUtilisateur, SQLITE3_FLOAT)));
        }
        else
        {
            $query="UPDATE Resoudre
            SET classement=:classement;
            WHERE utilisateur=:utilisateur
            AND enigme=:idEnigme
            AND partie=:idPartie";
            $this->con->executeQuery($query, array(
                "utilisateur" => array($emailUtilisateur, SQLITE3_TEXT),
                "enigme" => array($idEnigme, SQLITE3_INTEGER),
                "partie" => array($idPartie, SQLITE3_INTEGER),
                "classement" => array($classement, SQLITE3_INTEGER)));
        }
    }

    public function showAll() : void{
        $query = "SELECT * FROM Utilisateur";
        $this->con->executeQuery($query);
        $results=$this->con->getResults();
        foreach ($results as $row) {
            echo $row['email'] . '</br>';
            echo $row['pseudo'] . '</br>';
            echo $row['mdp'] . '</br>';
            echo $row['estAdmin'] . '</br>';
        }

    }
}