<?php

/**
 * Login.class [ MODEL ]
 * Responsável por autenticar, validar, e checar usuario do sistema de login!
 * 
 * @copyright (c) 2017, Welton Thierree TagPage
 */
class Login {

    private $Level;
    private $Email;
    private $Senha;
    private $Error;
    private $Result;

    /**
     * <b>Informar Level:</b> Informe o nÃ­vel de acesso mÃ­nimo para a Ã¡rea a ser protegida.
     * @param INT $Level = NÃ­vel mÃ­nimo para acesso
     */
    function __construct($Level) {
        $this->Level = (int) $Level;
    }

    /**
     * <b>Efetuar Login:</b> Envelope um array atribuitivo com Ã­ndices STRING user [email], STRING pass.
     * Ao passar este array na ExeLogin() os dados sÃ£o verificados e o login Ã© feito!
     * @param ARRAY $UserData = user [email], pass
     */
    public function ExeLogin(array $userData) {
        $this->Email = (string) strip_tags(trim($userData['user']));
        $this->Senha = (string) strip_tags(trim($userData['pass']));
        $this->setLogin();
    }

    function getResult() {
        return $this->Result;
    }

    function getError() {
        return $this->Error;
    }

    public function CheckLogin() {
        if ($this->Level == 3):
            $colum = "cliente";
        else:
            $colum = "usuario";
        endif;

        if (empty($_SESSION[$colum . 'login']) || $_SESSION[$colum . 'login'][$colum . '_perfil'] < $this->Level):
            unset($_SESSION[$colum . 'login']);
            return false;
        else:
            return true;
        endif;
    }

    public function PassGeneration($qtyCaraceters = 10) {
        //Letras minúsculas embaralhadas
        $smallLetters = str_shuffle('abcdefghijklmnopqrstuvwxyz');

        //Letras maiúsculas embaralhadas
        $capitalLetters = str_shuffle('ABCDEFGHIJKLMNOPQRSTUVWXYZ');

        //Números aleatórios
        $numbers = (((date('Ymd') / 12) * 24) + mt_rand(800, 9999));
        $numbers .= 1234567890;

        //Caracteres Especiais
        $specialCharacters = str_shuffle('!@#$%*-');

        //Junta tudo
        $characters = $capitalLetters . $smallLetters . $numbers . $specialCharacters;

        //Embaralha e pega apenas a quantidade de caracteres informada no parâmetro
        $password = substr(str_shuffle($characters), 0, $qtyCaraceters);

        //Retorna a senha
        return $password;
    }

    //PRIVATE
    private function setLogin() {
        if (!$this->Email || !$this->Senha || !Check::Email($this->Email)):
//            $senha = base64_encode($this->Senha);
            $senha = $this->Senha;
            $this->Error = ["Informe seu E-mail e senha para efetuar o login {$senha}", WS_INFOR];
            $this->Result = false;
        elseif (!$this->getUser()):
            $this->Error = ['Os dados informados não são compativeis', WS_ALERT];
            $this->Result = false;
        elseif (($this->Level != 3) && ($this->Result['usuario_perfil'] < $this->Level)):
            $this->Error = ["Desculpe {$this->Result['usuario_nome']}, você não tem permissão para acessar esta área", WS_ERROR];
            $this->Result = false;
        elseif (($this->Level != 3) && ($this->Result['usuario_status'] != 1)):
            $this->Error = ["Desculpe <b>{$this->Result['usuario_nome']}</b>, sua conta está bloqueada!", WS_INFOR];
            $this->Result = false;
        elseif (!$this->checkAcesso()):
            $this->Error = ["Desculpe este usuário já está logado em outro dispositivo!", WS_ERROR];
            $this->Result = false;
        elseif (!$this->checkExpiracao()):
            $this->Error = ["Desculpe este usuário expirou!", WS_ERROR];
            $this->Result = false;
        else:
            $this->Execute();
        endif;
    }

    private function getUser() {
//        $this->Senha = base64_encode($this->Senha);
        $this->Senha = $this->Senha;
        if ($this->Level == 3):
            $table = "clientes";
            $colum = "cliente";
        else:
            $table = "usuarios";
            $colum = "usuario";
        endif;

        $read = new Read;
        $read->ExeRead($table, "WHERE {$colum}_email = :e AND {$colum}_senha = :p", "e={$this->Email}&p={$this->Senha}");
        if ($read->getResult()):
            //setando os dados do usuário
            $Result = $read->getResult()[0];

            $this->Result = $Result;
            return true;
        else:
            return false;
        endif;
    }

    private function checkAcesso() {

        //verificar se existe acesso ativo desse usuario
        $id_usuario = $this->Result['usuario_id'];
        $ReadAce = new Read;
        $ReadAce->ExeRead("tp_acessos", "WHERE usuario_id = :id AND acesso_logado = 1 ", "id={$id_usuario}");
        //se existir acesso verificar o tempo do ping para saber se a pagina está aberta ou foi fechada 
        if ($ReadAce->getResult()):
            $data_last = $ReadAce->getResult()[0]['acesso_data_last'];
            $data_atual = date("Y-m-d H:i:s");
            $date = new DateTime($data_last);
            $date2 = new DateTime($data_atual);

            $intervalo = $date->diff($date2);

            if ($intervalo->i > 0 || $intervalo->s > 20):
                //se o periodo do last for maior que o periodo do ping o usuario não está logado(janela fechada ou sem conexão)
                //atualizar todos os acessos desse usuario para deslogado
                $upDados['acesso_logado'] = 0;
                $Update = new Update;
                $Update->ExeUpdate("tp_acessos", $upDados, "WHERE usuario_id = :id", "id={$id_usuario}");
                return true;
            else:
                //senão esse login está logado em outro dispositivo
//                WSErro("O usuario já está logado em outro dispositivo", WS_ERROR);
                return false;
            endif;
        else:
            return true;
        endif;
    }

    private function checkExpiracao() {

        //verificar se existe acesso ativo desse usuario
        $id_usuario = $this->Result['usuario_id'];
        $data_atual = date("Y-m-d");
        $ReadAce = new Read;
        $ReadAce->ExeRead("usuarios", "WHERE usuario_id = :id AND usuario_nivel > 1 AND usuario_data_exp < :data", "id={$id_usuario}&data={$data_atual}");
        //se existir acesso verificar o tempo do ping para saber se a pagina está aberta ou foi fechada 
        if ($ReadAce->getResult()):
            return false;
        else:
            return true;
        endif;
    }

    private function registraAcesso() {
        $Dados['usuario_id'] = $this->Result['usuario_id'];
        $Dados['usuario_nome'] = $this->Result['usuario_nome'];
        $Dados['acesso_data'] = date('Y-m-d H:i:s');
        $Dados['acesso_logado'] = 1;
        $Dados['acesso_data_last'] = date('Y-m-d H:i:s');

        $Create = new Create;
        $Create->ExeCreate("acessos", $Dados);

        return $Create->getResult();
    }

    private function Execute() {
        if (!session_id()):
            session_start();
        endif;

        if ($this->Level == 3):
            $colum = "cliente";
        else:
            $colum = "usuario";
        endif;

        //registrar o acesso
        $this->registraAcesso();

        $_SESSION[$colum . 'login'] = $this->Result;
        $this->Error = ["Olá {$this->Result[$colum . '_nome']}, seja bem vindo(a). Aguarde redirecionamento!", WS_ACCEPT];
        $this->Result = true;
    }

}
