import Serializer from "../data/serializer";
import Net from "../tools/net";

function UserService() {
  let cachedUserInfo = null;

  async function login({ username, password }) {
    let response = await Net.sendJsonRequest({
      method: "POST",
      url: "/api/users/login",
      data: { username, password },
    });

    if (response.status !== 200) {
      let responseData = JSON.parse(response.data);
      throw new Error(responseData.error);
    }
  }

  async function logout() {
    let response = await Net.sendJsonRequest({
      method: "POST",
      url: "/api/users/logout",
    });
    cachedUserInfo = null;
  }

  async function getUserInfo() {
    if (cachedUserInfo) {
      return cachedUserInfo;
    }
    let response = await Net.sendRequest({
      method: "GET",
      url: "/api/users/session/info",
    });

    if (response.status !== 200) {
      return null;
    }

    response = JSON.parse(response.data);
    cachedUserInfo = response;
    return response;
  }

  async function changePassword({ currentPassword, newPassword }) {
    let response = await Net.sendJsonRequest({
      method: "POST",
      url: "/api/users/newpassword",
      data: { currentPassword, newPassword },
    });

    if (response.status !== 200) {
      let responseData = JSON.parse(response.data);
      throw new Error(responseData.error);
    }
  }

  async function getUsers() {
    let response = await Net.sendRequest({
      method: "GET",
      url: "/api/users",
    });

    if (response.status !== 200) {
      let responseData = JSON.parse(response.data);
      throw new Error(responseData.error);
    }

    let userObjects = JSON.parse(response.data);
    return Serializer.deserializeUsers(userObjects);
  }

  async function createUser({ username, password, isAdmin }) {
    let response = await Net.sendJsonRequest({
      method: "POST",
      url: "/api/users",
      data: { username, password, is_admin: isAdmin },
    });

    if (response.status !== 200) {
      let responseData = JSON.parse(response.data);
      throw new Error(responseData.error);
    }

    let userObject = JSON.parse(response.data);
    let user = Serializer.deserializeUser(userObject);
    return user;
  }

  async function updateUser(userId, { isAdmin }) {
    let response = await Net.sendJsonRequest({
      method: "PUT",
      url: "/api/users/" + userId,
      data: { is_admin: isAdmin ? 1 : 0 },
    });

    if (response.status !== 200) {
      let responseData = JSON.parse(response.data);
      throw new Error(responseData.error);
    }

    let userObject = JSON.parse(response.data);
    let user = Serializer.deserializeUser(userObject);
    return user;
  }

  async function deleteUser(userId) {
    let response = await Net.sendJsonRequest({
      method: "DELETE",
      url: "/api/users/" + userId,
    });

    if (response.status !== 200) {
      let responseData = JSON.parse(response.data);
      throw new Error(responseData.error);
    }
  }

  return {
    login,
    logout,
    getUserInfo,
    changePassword,
    getUsers,
    createUser,
    updateUser,
    deleteUser,
  };
}

UserService = new UserService();

export default UserService;
