<?php

namespace SCF\Core;


class Authentication
{

    /**
     * @var Database
     */
    private $_db;

    /**
     * Login constructor.
     * @param Database $db
     */
    public function __construct(Database $db)
    {
        $this->_db = $db;
    }

    /**
     * @return string
     * @throws \Exception
     */
    private function createToken()
    {
        if (function_exists('random_bytes')) {
            $bytes = random_bytes(16);
            $str = bin2hex($bytes);
        } else if (function_exists('openssl_random_pseudo_bytes')) {
            $bytes = openssl_random_pseudo_bytes(16);
            $str = bin2hex($bytes);
        } else {
            $str = hash('sha256', uniqid(BLOWFISH, true));
        }
        return $str;

    }

    /**
     * @param string $username
     * @param string $password
     * @param $rememberMe
     * @return bool
     * @throws \Exception
     */
    public function loginAction($username = '', $password = '', $rememberMe)
    {
        $this->_db->query("SELECT `userId`, `username`, `password`, `email` FROM users WHERE username = :username OR email = :username LIMIT 0,1");
        $this->_db->bind(':username', $username);
        $temp = $this->_db->single();


        if ($temp !== false && hash('sha256',$password) ==  $temp['password']) {
            $_SESSION['scf_userId'] = $temp['userId'];


            if (isset($rememberMe)) {
                $identifier = $this->createToken();
                $securityToken = $this->createToken();
                $time = date("Y-m-d H:i:s", time());

                $this->_db->query("INSERT INTO users_tokens (userId, identifier, securitytoken, createDate) VALUES (:userId, :identifier, :securitytoken, :created)");
                $this->_db->bind(':userId', $temp['userId']);
                $this->_db->bind(':identifier', $identifier);
                $this->_db->bind(':securitytoken', sha1($securityToken));
                $this->_db->bind(':created', $time);
                $this->_db->execute();
                setcookie('scf_identifier', $identifier, time() + (3600 * 24 * 30));
                setcookie('scf_token', $securityToken, time() + (3600 * 24 * 30));
            }
            return true;
        } else {
            session_destroy();
            return false;
        }
    }

    /**
     * @return bool
     */
    public function isLogin()
    {
        $this->checkLogin();

        if (isset($_SESSION['scf_userId'])) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * Check if LoginToken for user exists
     */
    public function checkLogin()
    {
        if (!isset($_SESSION['scf_userId']) && isset($_COOKIE['scf_identifier']) && isset($_COOKIE['scf_token'])) {
            $identifier = $_COOKIE['scf_identifier'];
            $securityToken = $_COOKIE['scf_token'];

            $this->_db->query("SELECT * FROM users_tokens WHERE identifier = :identifier");
            $this->_db->bind(':identifier', $identifier);
            $this->_db->execute();

            $temp = $this->_db->single();

            if (sha1($securityToken) !== $temp['securitytoken']) {

            } else {
                $newToken = $this->createToken();
                $this->_db->query("UPDATE users_tokens SET securitytoken = :token WHERE identifier = :identifier");
                $this->_db->bind(':token', $newToken);
                $this->_db->bind(':identifier', $identifier);
                setcookie('scf_identifier', $identifier, time() + (3600 * 24 * 30));
                setcookie('scf_token', $newToken, time() + (3600 * 24 * 30));

                $_SESSION['scf_userId'] = $temp['userId'];

            }
        }
    }


    public function logout()
    {
        if(isset($_COOKIE['scf_identifier'])) {
            $this->_db->query("DELETE FROM users_tokens WHERE userId = {$_SESSION['admin_userId']}");
        }
        setcookie('scf_identifier', null , -1);
        setcookie('scf_token', null , -1);
        session_destroy();
        return true;
    }

    /**
     * @param string $username
     * @param string $password
     * @param string $email
     * @param string $gender
     * @return string
     * @throws \Exception
     */
    public function registerAccount($username = '', $password = '', $email = '', $gender = 'n')
    {
        $this->_db->query("SELECT username, email FROM users WHERE username = :reguser OR email = :regemail");
        $this->_db->bind(':reguser', $username);
        $this->_db->bind(':regemail', $email);
        $this->_db->execute();

        if ($this->_db->rowCount() == 1) {
            return 'register_error';
        } else {

            $this->saveDataInDatabase($username, $password, $email, $gender);

            return 'register_success';
        }

    }

    /**
     * @param $username
     * @param $password
     * @param $email
     * @param $gender
     * @throws \Exception
     */
    private function saveDataInDatabase($username, $password, $email, $gender)
    {
        $this->_db->query("INSERT INTO users (username, passwort, avatar, gender, email, accountActive, activationHash) 
                                             VALUES (:username, :password, 'm2', :gender, :email, '0', :activation)");
        $this->_db->bind(':username', $username);
        $this->_db->bind(':password', password_hash($password, PASSWORD_BCRYPT));
        $this->_db->bind(':gender', $gender);
        $this->_db->bind(':email', $email);
        $this->_db->bind(':activation', $this->createToken());
        $this->_db->execute();
    }
}