async function createSubscription() {
    while (true) {
        try {
            console.log("[Realtime] Connecting...");

            const response = await epoxyFetch(
                website + "/api/realtime",
                {
                    headers: {
                        Authorization: `Bearer ${UserAuth}`,
                        Accept: "text/event-stream"
                    }
                }
            );

            console.log("[Realtime] SSE connected");

            for await (const event of events(response)) {
                console.log("[Realtime] Event:", event);

                if (event.event === "PB_CONNECT") {
                    const data = JSON.parse(event.data);

                    console.log("[Realtime] Connected:", data.clientId);

                    await subscribe(data.clientId);
                }

                if (event.event === "Messages/*") {
                    const data = JSON.parse(event.data);

                    await SubscriptionExtra(data, data.record);
                }
            }

            console.warn("[Realtime] SSE stream ended");
        } catch (error) {
            console.error("[Realtime] Connection failed:", error);
        }

        console.log("[Realtime] Reconnecting in 2 seconds...");
        await new Promise(resolve => setTimeout(resolve, 2000));
    }
}
async function SubscriptionExtra(event, eventRecord) {
        const container = document.getElementById("Messages");
      const oldClientHeight = container.clientHeight;
    const oldHeight = container.scrollHeight;
    const oldScrollTop = container.scrollTop;
    if (document.visibilityState !== "visible") {
        console.log("Creating notification", Notification.permission);
        const img = "GroupLink-Fancy.png";
        const text = event.record["Creator"];
        const notification = new Notification(`${event.record["Creator"]} + ${event.record["Message"]}`);
     }
     if (oldScrollTop + oldClientHeight >= oldHeight - 5) {
          await f_createMessage(event.record["Creator"], event.record["Message"]);
          container.scrollTop = container.scrollHeight;
     } else {
          await f_createMessage(event.record["Creator"], event.record["Message"]);
     }
}
async function subscribe(clientId) {
        const body = {
      clientId,
      subscriptions: [
        "Messages/*"
      ]
    }
  const response = await epoxyFetch(website + "/api/realtime", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "Authorization": `Bearer ${UserAuth}`
      },
      body: JSON.stringify(body)
    });

    if (!response.ok && !response != "204") {
      throw new Error(`HTTP error! Status: ${response.status}`);
    }
}

async function createGC(Owner, Name, Avatar){
createGCDiv.style = "visibility: hidden;"
const body = {
    "Owner": Owner, 
    "Name": Name,
    "Icon": Avatar
};
console.log(document.getElementById("GC-Create-Icon").files[0]);
const record = await PostData("Groups",body)

await addToGC(record.id, Owner, "Owner")
}
async function addFriend(UserName) {
  //alert(UserName)
  var friendUserID = await getUserIDFromUsername(UserName)
  //alert(friendUserID)
  const body = {
    "Status": "Pending",
    "Creator": UserID,
    "Receiver": friendUserID
};
//alert(body)
 var record = await PostData("Friends", body)
}
async function removeFriend(userid, otherid) {
  var friendID = await getFriendRecordID(userid, otherid)
  //alert(friendID)
  await DeleteData("Friends", friendID)
}
async function acceptFriend(userid, otherid) {
  var friendID = await getFriendRecordID(userid, otherid)
  //alert(friendID)
  const body = {
    "Status": "Accepted"
};
 var record = await UpdateData(friendID, "Friends", body)
}
async function addToGC(GroupID, UserID, Permission) { 
const body = {
  "User": UserID,
  "Group": GroupID,
  "Permissions": Permission
};
const record = await PostData("GroupUsers",body)
};
async function getPendingFriendRequests(UserID) {
    const filter = encodeURIComponent(
        `Status="Pending" && Receiver="${UserID}"`
    );

    const data = await GetData(
        "Friends",
        "",
        `?filter=${filter}&perPage=500`
    );

    return data.items.map(request => request.Creator);
}
async function getFriends(UserID) {
    const filter = encodeURIComponent(
        `(Status="Accepted") && (Creator="${UserID}" || Receiver="${UserID}")`
    );

    const data = await GetData(
        "Friends",
        "",
        `?filter=${filter}&perPage=500`
    );
    alert(JSON.stringify(data))
    return data.items.map(friend =>
        friend.Creator === UserID
            ? friend.Receiver
            : friend.Creator
    );
}
async function getFriendRecordID(userID, otherUserID) {
    const filter = encodeURIComponent(
        `((Creator="${userID}" && Receiver="${otherUserID}") || (Creator="${otherUserID}" && Receiver="${userID}"))`
    );

    const data = await GetData(
        "Friends",
        "",
        `?filter=${filter}&perPage=1`
    );

    return data.items.length > 0 ? data.items[0].id : null;
}
async function getUserIDFromUsername(username) {
    const filter = encodeURIComponent(
        `Username="${username}"`
    );

    const data = await GetData(
        "users",
        "",
        `?filter=${filter}&perPage=1`
    );

    if (!data.items.length) {
        return null;
    }

    return data.items[0].id;
}


async function sendMessages(GroupID, UserID, Message) { 
const body = {
  "Creator": UserID,
  "Group": GroupID,
  "Message": Message
};

const record = await PostData("Messages",body)
};

async function getUserGroups(UserID) {
    const filter = encodeURIComponent(`User="${UserID}"`);

    const data = await GetData(
        "GroupUsers",
        "",
        `?filter=${filter}&perPage=500`
    );
    //alert(JSON.stringify(data))
    return data.items.map(record => record.Group);
}
async function getGroupUsers(GroupID) {
    const filter = encodeURIComponent(`Group="${GroupID}"`);

    const data = await GetData(
        "GroupUsers",
        "",
        `?filter=${filter}&perPage=500`
    );
    //alert(JSON.stringify(data))
    return data.items.map(record => record.User);
}

async function DeleteGC() {
    //alert("That isn't possible right now, please try again later.")
}

async function KickUser(UserID, GroupChat) {
    const filter = encodeURIComponent(
        `User="${UserID}" && Group="${GroupChat}"`
    );

    const data = await GetData(
        "GroupUsers",
        "",
        `?filter=${filter}&perPage=1`
    );

    if (data.items.length === 0) {
        throw new Error("User is not a member of this group.");
    }

    await DeleteData("GroupUsers", data.items[0].id);
}

async function getGroupInfo(GroupID) {
const record = await GetData("Groups",GroupID)
return(record)
}
async function getFile(collection,record,fileName){
    var response = await epoxyFetch(website + "/api/files/" + collection + "/" + record + "/" + fileName)
    
    var text = await response.blob()
    return(text)
}

async function getMessages(GroupID, MessageTime) {
  if (!reachedChatEnd){
    const filter = encodeURIComponent(
        `Group="${GroupID}" && created<"${MessageTime}"`
    );
    var response = await GetData(
        "Messages",
        "",
        `?page=1&perPage=50&filter=${filter}&sort=-created`
    );
    response = response["items"]
    currentLatestMessageTime = (response[response.length - 1])["created"]
    console.log(
    "Oldest on page:",
    response.length ? response[response.length - 1].created : "none"
);
console.log(
    "Page:",
    response.map(m => m.id)
);
    response.reverse()
    if (Object.keys(response).length === 0){
      reachedChatEnd = true
        return([])
    }
    return(response)
} else {
  return([])
}

}

async function getUserCache(id) {
if (Object.hasOwn(UserCache, id)){
return(UserCache[id])
} else {
  var response = await GetData("users",id)
  UserCache[id] = response//["items"]
  return(UserCache[id])
}
}

async function checkWisp(url, timeout = 5000) {
    return new Promise((resolve) => {
        const ws = new WebSocket(url);

        const timer = setTimeout(() => {
            ws.close();
            resolve(false);
        }, timeout);

        ws.onopen = () => {
            clearTimeout(timer);
            ws.close();
            resolve(true);
        };

        ws.onerror = () => {
            clearTimeout(timer);
            resolve(false);
        };

        ws.onclose = () => {
            clearTimeout(timer);
        };
    });
}