<?php
    defined('BASEPATH') OR exit('No direct script access allowed');

    class UserModel extends CI_Model
    {

        function __construct()
        {
            parent::__construct();
            $this->load->model('BlogModel', '', TRUE);
            $this->load->model('NotificationModel', '', TRUE);
        }

        function getUser($username)
        {
            $result = $this->db->query('SELECT u.ID, u.username, u.displayname, u.email, u.rank, u.dateCreated, s.profilePicture, s.headerImage, s.about, s.socialNetworks, s.showAds, s.gender, s.language, s.country, s.birthdate, s.birthyear, s.receiveEmails, s.receiveNewsletter FROM users u INNER JOIN user_settings s ON s.ID = u.ID WHERE username = ? AND activated = TRUE AND isDeleted = FALSE LIMIT 1', [strtolower($username)])->result_array();
            if (empty($result)) {
                return null;
            }
            $result = $this->setDefaultImages($result);
            $result = $this->setRankname($result);
            return $result;
        }

        public function setDefaultImages($userList)
        {
            for ($i = 0; $i < sizeof($userList); $i++) {
                if ((isset($userList[$i]['headerImage']) && ($userList[$i]['headerImage'] == '' || $userList[$i]['headerImage'] == NULL)) || !isset($userList[$i]['headerImage'])) {
                    $userList[$i]['headerImage'] = 'https://cdn.kinogofdog.eu' . '/' . $userList[$i]['displayname'];
                }
                if (isset($userList[$i]['profilePicture']) && $userList[$i]['profilePicture'] == '') {
                    $userList[$i]['profilePicture'] = base_url('/f/8d204712d8132b36d765640ce775ce15');
                }
            }
            return $userList;
        }

        public function setRankname($userList)
        {
            for ($i = 0; $i < sizeof($userList); $i++) {
                if (isset($userList[$i]['rank'])) {
                    $userList[$i]['rankName'] = $this->GeneralModel->getRankName($userList[$i]['rank']);
                }
            }
            return $userList;
        }

        public function getUserIDByUsername($username)
        {
            $result = $this->db->query('SELECT ID FROM users WHERE username = ?', [$username])->result_array();
            return $result;
        }

        public function getFollowers($id)
        {
            $this->db->cache_off();
            $followers = $this->db->query('SELECT u.ID, followedSince, username, displayname, profilePicture, headerImage FROM user_followers LEFT JOIN users u ON u.ID = followerUserID LEFT JOIN user_settings s ON s.ID = followerUserID WHERE followedUserID = ? AND u.activated = TRUE AND u.isDeleted = FALSE ORDER BY followedSince DESC', [$id])->result_array();
            $this->db->cache_on();
            $followers = $this->setDefaultImages($followers);
            $followers = $this->mergeFollowerCount($followers);
            return $followers;
        }

        public function mergeFollowerCount($users)
        {
            foreach ($users as $i => $user) {
                $this->db->cache_off();
                $followerCount = $this->db->query('SELECT count(*) followerCount FROM user_followers WHERE followedUserID = ?', [$user['ID']])->result_array();
                $this->db->cache_on();
                $users[$i]['followerCount'] = $followerCount[0]['followerCount'];
            }
            return $users;
        }

        function getUserByID($id)
        {
            $result = $this->db->query('SELECT u.ID, originalName, username, displayname, email, rank, profilePicture, headerImage, activated, about, lastLogin, socialNetworks, showAds, dateCreated, gender, language, country, birthdate, birthyear, receiveEmails, receiveNewsletter FROM users u LEFT JOIN user_settings s ON s.ID = u.ID WHERE u.ID = ? AND activated = TRUE AND isDeleted = FALSE LIMIT 1', [$id])->result_array();
            if (empty($result)) {
                return null;
            }
            $result = $this->setDefaultImages($result);
            $result = $this->setRankname($result);
            return $result;
        }

        function getUserEmailByID($id)
        {
            $result = $this->db->query('SELECT email FROM users WHERE ID = ? AND activated = TRUE AND isDeleted = TRUE', [$id])->result_array();
            return !empty($result) ? $result[0]['email'] : '';
        }

        public function getFollowing($id)
        {
            $this->db->cache_off();
            $following = $this->db->query('SELECT u.ID, followedSince, username, displayname, profilePicture, headerImage FROM user_followers LEFT JOIN users u ON u.ID = followedUserID LEFT JOIN user_settings s ON s.ID = followedUserID WHERE followerUserID = ? AND isDeleted = FALSE ORDER BY followedSince DESC', [$id])->result_array();
            $this->db->cache_on();
            $following = $this->setDefaultImages($following);
            $following = $this->mergeFollowerCount($following);
            return $following;
        }

        function getUserComments($id, $count, $offset)
        {
            $comments = $this->db->query('SELECT c.* FROM blog_post_comments c WHERE userID = ? ORDER BY date DESC LIMIT ? OFFSET ?', [$id, $count, $offset])->result_array();
            $comments = $this->BlogModel->mergePostTranslation($comments, false, null, 'postID');
            return $comments;
        }

        function getUserBlogPosts($id, $count, $offset)
        {
            $posts = $this->db->query('SELECT * FROM blog_post WHERE state = 1 AND authorID = ? ORDER BY initialRelease DESC LIMIT ? OFFSET ?', [$id, $count, $offset])->result_array();
            $posts = $this->BlogModel->mergePostTranslation($posts);
            return $posts;
        }


        function getUserStats($userID)
        {
            $result = [];
            $this->db->cache_off();
            $user = $this->db->query('SELECT
  COUNT(*)                   postCount,
  (SELECT COUNT(*)
   FROM user_followers
   WHERE followedUserID = ?) followerCount,
  (SELECT COUNT(*)
   FROM user_followers
   WHERE followerUserID = ?) followedCount
FROM user_posts
WHERE userID = ?', [$userID, $userID, $userID])->result_array()[0];
            $result['postCount'] = $user['postCount'];
            $result['followerCount'] = $user['followerCount'];
            $result['followedCount'] = $user['followedCount'];
            $blogResults = $this->db->query('SELECT COUNT(*) blogCount, (SELECT COUNT(*) FROM blog_post_comments WHERE userID = ?) commentCount FROM blog_post WHERE state = 1 AND authorID = ?', [$userID, $userID])->result_array()[0];
            $result['blogCount'] = $blogResults['blogCount'];
            $result['commentCount'] = $blogResults['commentCount'];
            $this->db->cache_on();
            return $result;
        }

        function isFollowing($followerID, $followingID)
        {
            $this->db->cache_off();
            $response = $this->db->query('SELECT followedUserID FROM user_followers WHERE followerUserID = ? AND followedUserID = ?', [$followerID, $followingID])->result_array();
            $this->db->cache_off();
            return !empty($response);
        }

        function unfollow($followerID, $followedID)
        {
            $this->db->query('DELETE FROM user_followers WHERE followerUserID = ? AND followedUserID = ?', [$followerID, $followedID]);

            // Remove notification
            $this->NotificationModel->removeNotification($followerID, $followedID, $followedID, 'users.newFollower');
        }

        function follow($followerID, $followedID)
        {
            $this->db->query('INSERT INTO user_followers (followerUserID, followedUserID) VALUES (?, ?)', [$followerID, $followedID]);

            // Send notification to followed user
            $this->NotificationModel->userNotificationNewFollower($followerID, $followedID);
        }

        function updateProfile($data, $id)
        {
            function in_data1($val) {
                return in_array($val, ['username', 'displayname', 'email', 'password']);
            }

            $data1 = array_filter($data, "in_data1");
            if(!empty($data1)) {
                $this->db->where('ID', $id);
                $this->db->update('users', $data1);
            }

            $data2 = array_diff($data, $data1);
            if(!empty($data2)) {
                $this->db->where('ID', $id);
                $this->db->update('user_settings', $data2);
            }
        }

        function insertIntoHistory($data)
        {
            if(isset($data['password'])) {
                unset($data['password']);
                $data['passwordChanged'] = true;
            }

            $this->db->insert('user_settings_history', $data);
        }

        function getUserList($amount, $offset)
        {
            $data = $this->db->query('SELECT u.ID, username, displayname, rank, profilePicture, headerImage, activated, showAds, receiveEmails, receiveNewsletter, dateCreated, isCurrentlyOnline, lastLogin, loginMethod, language, country, gender
              FROM users u
                LEFT JOIN user_settings s ON u.ID = s.ID
              LIMIT ? OFFSET ?', [$amount, $offset])->result_array();
            $data = $this->setDefaultImages($data);
            $data = $this->setRankname($data);
            return $data;
        }

        public function updateOnline($id)
        {
            $this->db->query('UPDATE users SET isCurrentlyOnline = 1, lastOnlineUpdate = NOW() WHERE ID = ? LIMIT 1', [$id]);
        }

        function getActiveUsers($count)
        {
            $data = $this->db->query('SELECT username, displayname, profilePicture, lastLogin, (SELECT COUNT(*) FROM user_followers WHERE followedUserID = u.ID) follower_count FROM users u LEFT JOIN user_settings s ON s.ID = u.ID WHERE isCurrentlyOnline = TRUE AND activated = TRUE AND isDeleted = FALSE ORDER BY lastLogin DESC LIMIT ?', [$count])->result_array();
            $data = $this->setDefaultImages($data);
            return $data;
        }

        public function getNewestUsers($count)
        {
            $data = $this->db->query('SELECT username, displayname, profilePicture, dateCreated, (SELECT COUNT(*) FROM user_followers WHERE followedUserID = u.ID) follower_count FROM users u LEFT JOIN user_settings s ON s.ID = u.ID WHERE activated = TRUE AND isDeleted = FALSE ORDER BY dateCreated DESC LIMIT ?', [$count])->result_array();
            $data = $this->setDefaultImages($data);
            return $data;
        }

        public function searchUsers($query, $rank = '', $region = '', $lang = '', $amount = 3, $offset = 0)
        {
            $conditions = [];
            $inputs = [];
            if ($query !== '') {
                $conditions[] = 'username RLIKE ?';
                $inputs[] = $query;
            }
            if ($rank !== '') {
                $conditions[] = 'rank = ?';
                $inputs[] = $rank;
            }
            if ($region !== '') {
                $conditions[] = 'country = ?';
                $inputs[] = $region;
            }
            if ($lang !== '') {
                $conditions[] = 'language = ?';
                $inputs[] = $lang;
            }

            $dbClause = join(' AND ', $conditions);
            $inputs[] = $amount;
            $inputs[] = $offset;
            $data = $this->db->query('SELECT username, displayname, profilePicture, headerImage, about, rank FROM users u LEFT JOIN user_settings s ON s.ID = u.ID WHERE activated = TRUE AND isDeleted = FALSE AND ' . $dbClause . ' LIMIT ? OFFSET ?', $inputs)->result_array();

            $data = $this->setDefaultImages($data);
            $data = $this->setRankname($data);

            return $data;
        }

        public function getAvailableCountries()
        {
            return $this->db->query('SELECT country, count(*) countryUserCount FROM user_settings WHERE country IS NOT NULL AND country != "" GROUP BY country ORDER BY country')->result_array();
        }

        public function getAvailableLanguages()
        {
            return $this->db->query('SELECT language, count(*) langUserCount FROM user_settings GROUP BY language ORDER BY language')->result_array();
        }

        public function deleteUser($id)
        {
            $this->db->query('UPDATE users SET isDeleted = TRUE, isCurrentlyOnline = FALSE, lastOnlineUpdate = NULL WHERE ID = ?', [$id])->result_array();
        }

        public function getPermissions($userID)
        {
            $this->db->cache_off();
            $result = $this->db->query('SELECT * FROM user_permissions WHERE userID = ?', [$userID])->result_array();
            $this->db->cache_on();

            $perms = [];

            foreach ($result as $item) {
                $perms[] = $item['permissionType'] . '.' . $item['permissionName'];
            }

            return $perms;
        }

        public function hasPermission($userID, $permType, $permName)
        {
            $this->db->cache_off();
            $result = $this->db->query('SELECT ID FROM user_permissions WHERE userID = ? AND permissionType = ? AND permissionName = ?', [$userID, $permType, $permName])->result_array();
            $this->db->cache_on();
            return !empty($result);
        }

        public function addPermission($userID, $permissionGroup, $permissionName, $givenBy)
        {
            $this->db->query('INSERT INTO user_permissions (userID, permissionType, permissionName, givenBy) VALUES (?, ?, ?, ?)', [$userID, $permissionGroup, $permissionName, $givenBy]);
        }

        public function revokePermission($userID, $permissionGroup, $permissionName)
        {
            $this->db->query('DELETE FROM user_permissions WHERE userID = ? AND permissionType = ? AND permissionName = ?', [$userID, $permissionGroup, $permissionName]);
        }
    }