<?php
    class OpenSim
    {
        public function isLoginValid($name, $password)
        {
            global $RUNTIME;

            $nameParts = explode(" ", trim($name));
            if(count($nameParts) != 2) {
                return false;
            }

            $statementUser = $RUNTIME['PDO']->prepare("SELECT PrincipalID FROM UserAccounts WHERE FirstName = ? AND LastName = ? LIMIT 1");
            $statementUser->execute($nameParts);

            while($rowUser = $statementUser->fetch()) {
                $statementAuth = $RUNTIME['PDO']->prepare("SELECT passwordHash,passwordSalt FROM auth WHERE UUID = ? LIMIT 1");
                $statementAuth->execute(array($rowUser['PrincipalID']));

                if ($rowAuth = $statementAuth->fetch()) {
                    return md5(md5($_POST['password']).":".$rowAuth['passwordSalt']) == $rowAuth['passwordHash'];
                }
            }

            return false;
        }

        public function getUserName($userID)
        {
            global $RUNTIME;
            
            if ($userID == "00000000-0000-0000-0000-000000000000") {
                return "Unknown User";
            }

            if (isset($RUNTIME['CACHE']['USERNAME'][$userID])) {
                return $RUNTIME['CACHE']['USERNAME'][$userID];
            }

            $statementUser = $RUNTIME['PDO']->prepare("SELECT FirstName,LastName FROM UserAccounts WHERE PrincipalID = ?");
            $statementUser->execute(array($userID));

            if ($rowUser = $statementUser->fetch()) {
                $RUNTIME['CACHE']['USERNAME'][$userID] = $rowUser['FirstName']." ".$rowUser['LastName'];
                return $rowUser['FirstName']." ".$rowUser['LastName'];
            }

            $statementGridUser = $RUNTIME['PDO']->prepare("SELECT UserID FROM GridUser");
            $statementGridUser->execute();

            while ($rowGridUser = $statementGridUser->fetch()) {
                $userData = explode(";", $rowGridUser['UserID']);

                if (count($userData) >= 3) {
                    $dbUserID = $userData[0];
                    $dbUserName = $userData[2];

                    $RUNTIME['CACHE']['USERNAME'][$userID] = $dbUserName;

                    if ($dbUserID == $userID) {
                        return $dbUserName;
                    }
                }
            }

            $statementFriends = $RUNTIME['PDO']->prepare("SELECT PrincipalID FROM Friends");
            $statementFriends->execute();

            while ($rowFriends = $statementFriends->fetch()) {
                $userData = explode(";", $rowFriends['PrincipalID']);

                if (count($userData) == 4) {
                    $dbUserID = $userData[0];
                    $dbUserName = $userData[2];

                    $RUNTIME['CACHE']['USERNAME'][$userID] = $dbUserName;

                    if ($dbUserID == $userID) {
                        return $dbUserName;
                    }
                }
            }

            return "Unknown User";
        }

        public function getUserUUID($userName)
        {
            global $RUNTIME;
            
            $statementUser = $RUNTIME['PDO']->prepare("SELECT PrincipalID,FirstName,LastName FROM UserAccounts");
            $statementUser->execute();

            while ($rowUser = $statementUser->fetch()) {
                $sqlUserName = $rowUser['FirstName']." ".$rowUser['LastName'];

                if ($sqlUserName == $userName) {
                    return $rowUser['PrincipalID'];
                }
            }

            return null;
        }

        public function getRegionName($regionID)
        {
            global $RUNTIME;
            
            $statementRegion = $RUNTIME['PDO']->prepare("SELECT regionName FROM regions WHERE uuid = ?");
            $statementRegion->execute(array($regionID));

            if ($rowRegion = $statementRegion->fetch()) {
                return $rowRegion['regionName'];
            }

            return "Unknown Region";
        }

        public function getPartner($userID)
        {
            global $RUNTIME;
            
            $statement = $RUNTIME['PDO']->prepare("SELECT profilePartner FROM userprofile WHERE useruuid = ?");
            $statement->execute(array($userID));

            while ($row = $statement->fetch()) {
                if ($row['profilePartner'] != "00000000-0000-0000-0000-000000000000") {
                    return $row['profilePartner'];
                }
            }

            return null;
        }

        public function allowOfflineIM($userID)
        {
            global $RUNTIME;
            
            $statement = $RUNTIME['PDO']->prepare("SELECT imviaemail FROM usersettings WHERE useruuid = ?");
            $statement->execute(array($userID));

            if ($row = $statement->fetch()) {
                return strtoupper($row['imviaemail']);
            }

            return "FALSE";
        }

        public function getUserMail($userID)
        {
            global $RUNTIME;
            
            $statement = $RUNTIME['PDO']->prepare("SELECT Email FROM UserAccounts WHERE PrincipalID = ?");
            $statement->execute(array($userID));

            if ($row = $statement->fetch()) {
                return $row['Email'];
            }

            return "";
        }

        public function getUserCount()
        {
            global $RUNTIME;
            
            $statementUser = $RUNTIME['PDO']->prepare("SELECT COUNT(*) FROM UserAccounts");
            $statementUser->execute();
            return $statementUser->fetchColumn();
        }

        public function getRegionCount()
        {
            global $RUNTIME;
            
            $statementUser = $RUNTIME['PDO']->prepare("SELECT COUNT(*) FROM regions");
            $statementUser->execute();
            return $statementUser->fetchColumn();
        }

        public function getOnlineCount()
        {
            global $RUNTIME;

            $statementUser = $RUNTIME['PDO']->prepare("SELECT COUNT(*) FROM Presence");
            $statementUser->execute();
            return $statementUser->fetchColumn();
        }

        public function deleteUser($uuid): bool
        {
            global $RUNTIME;

            try {
                $RUNTIME['PDO']->beginTransaction();

                $statementAuth = $RUNTIME['PDO']->prepare('DELETE FROM auth WHERE UUID = ?');
                $statementAuth->execute([$uuid]);

                $statementAgentPrefs = $RUNTIME['PDO']->prepare('DELETE FROM AgentPrefs WHERE PrincipalID = ?');
                $statementAgentPrefs->execute([$uuid]);

                $statementAvatars = $RUNTIME['PDO']->prepare('DELETE FROM Avatars WHERE PrincipalID = ?');
                $statementAvatars->execute([$uuid]);

                $statementGridUser = $RUNTIME['PDO']->prepare('DELETE FROM GridUser WHERE UserID = ?');
                $statementGridUser->execute([$uuid]);

                $statementEstateUser = $RUNTIME['PDO']->prepare('DELETE FROM estate_users WHERE uuid = ?');
                $statementEstateUser->execute([$uuid]);

                $statementEstateBan = $RUNTIME['PDO']->prepare('DELETE FROM estateban WHERE bannedUUID = ?');
                $statementEstateBan->execute([$uuid]);

                $statementHgTraveling = $RUNTIME['PDO']->prepare('DELETE FROM hg_traveling_data WHERE UserID = ?');
                $statementHgTraveling->execute([$uuid]);

                $statementUserIdentitys = $RUNTIME['PDO']->prepare('DELETE FROM UserIdentitys WHERE PrincipalID = ?');
                $statementUserIdentitys->execute([$uuid]);

                $statementFriends = $RUNTIME['PDO']->prepare('DELETE FROM Friends WHERE PrincipalID = ? OR Friend = ?');
                $statementFriends->execute([$uuid, $uuid]);

                $statementImOffline = $RUNTIME['PDO']->prepare('DELETE FROM im_offline WHERE PrincipalID = ?');
                $statementImOffline->execute([$uuid]);

                $statementInventoryFolders = $RUNTIME['PDO']->prepare('DELETE FROM inventoryfolders WHERE agentID = ?');
                $statementInventoryFolders->execute([$uuid]);

                $statementInventoryItems = $RUNTIME['PDO']->prepare('DELETE FROM inventoryitems WHERE avatarID = ?');
                $statementInventoryItems->execute([$uuid]);

                $statementGroupMembership = $RUNTIME['PDO']->prepare('DELETE FROM os_groups_membership WHERE PrincipalID = ?');
                $statementGroupMembership->execute([$uuid]);

                $statementGroupRoles = $RUNTIME['PDO']->prepare('DELETE FROM os_groups_rolemembership WHERE PrincipalID = ?');
                $statementGroupRoles->execute([$uuid]);

                $statementGroupRoles = $RUNTIME['PDO']->prepare('DELETE FROM Presence WHERE UserID = ?');
                $statementGroupRoles->execute([$uuid]);

                $statementMute = $RUNTIME['PDO']->prepare('DELETE FROM MuteList WHERE AgentID = ? OR MuteID = ?');
                $statementMute->execute([$uuid, $uuid]);

                $statementUserAccounts = $RUNTIME['PDO']->prepare('DELETE FROM UserAccounts WHERE PrincipalID = ?');
                $statementUserAccounts->execute([$uuid]);

                $statementUserData = $RUNTIME['PDO']->prepare('DELETE FROM userdata WHERE UserId = ?');
                $statementUserData->execute([$uuid]);

                $statementUserNotes = $RUNTIME['PDO']->prepare('DELETE FROM usernotes WHERE targetuuid = ?');
                $statementUserNotes->execute([$uuid]);

                $statementUserProfile = $RUNTIME['PDO']->prepare('DELETE FROM userprofile WHERE useruuid = ?');
                $statementUserProfile->execute([$uuid]);

                $statementUserSettings = $RUNTIME['PDO']->prepare('DELETE FROM usersettings WHERE useruuid = ?');
                $statementUserSettings->execute([$uuid]);

                $RUNTIME['PDO']->commit();

                return true;
            } catch (Exception $pdoException) {
                $RUNTIME['PDO']->rollBack();
                error_log('Could not delete account '.$uuid.': '.$pdoException->getMessage());
                return false;
            }
        }

        public function gen_uuid()
        {
            return sprintf( '%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
                // 32 bits for "time_low"
                mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ),
        
                // 16 bits for "time_mid"
                mt_rand( 0, 0xffff ),
        
                // 16 bits for "time_hi_and_version",
                // four most significant bits holds version number 4
                mt_rand( 0, 0x0fff ) | 0x4000,
        
                // 16 bits, 8 bits for "clk_seq_hi_res",
                // 8 bits for "clk_seq_low",
                // two most significant bits holds zero and one for variant DCE1.1
                mt_rand( 0, 0x3fff ) | 0x8000,
        
                // 48 bits for "node"
                mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff )
            );
        }
    }