<file_sep>The app allows users to shorten long URLs and see the links he created.

    GET /
        if user is logged in:
            redirect -> /urls
        if user is not logged in:
            redirect -> /login

    GET /urls
        if user is not logged in:
            returns a 401 response, HTML with a relevant error message and a link to /login
        if user is logged in:
            returns a 200 response, HTML with:
            the site header (see below)
            a table of urls the user has created, each row:
                short url
                long url
                edit button -> GET /urls/:id
                delete button -> POST /urls/:id/delete
                date created (stretch)
                number of visits (stretch)
                number of unique visits (stretch)
            a link to "Create a New Short Link" -> /urls/new

    GET /urls/new
        if user is not logged in:
            returns a 401 response, HTML with:
            error message
            a link to /login
        if user is logged in:
            returns a 200 response, HTML with:
            the site header (see below)
            a form, which contains:
                text input field for the original URL
                submit button -> POST /urls

    GET /urls/:id
        if url w/ :id does not exist:
            returns a 404 response, HTML with a relevant error message
        if user is not logged in:
            returns a 401 response, HTML with a relevant error message and a link to /login
        if logged in user does not match the user that owns this url:
            returns a 403 response, HTML with a relevant error message
        if all is well:
            returns a 200 response, HTML with:
            the short url
            date created (stretch)
            number of visits (stretch)
            number of unique visits (stretch)
            a form, which contains:
                the long url
                "update" button -> POST /urls/:id
                "delete" button -> POST /urls/:id/delete

    GET /u/:id
        if url with :id exists:
            redirect -> the corresponding longURL
        otherwise:
            returns a 404 response, HTML with a relevant error message

    POST /urls
        if user is logged in:
            generates a shortURL, saves the link and associates it with the user
            redirect -> /urls/:id
        if user is not logged in:
            returns a 401 response, HTML with a relevant error message and a link to /login

    POST /urls/:id
        if url with :id does not exist:
            returns a 404 response, HTML with a relevant error message
        if user is not logged in:
            returns a 401 response, HTML with a relevant error message and a link to /login
        if user does not match the url owner:
            returns a 403 response, HTML with a relevant error message
        if all is well:
            updates the url
            redirect -> /urls/:id

    GET /login
        if user is logged in:
            redirect -> /
        if user is not logged in:
            returns a 200 response, HTML with:
            a form which contains:
                input fields for email and password
                submit button -> POST /login

    GET /register
        if user is logged in:
            redirect -> /
        if user is not logged in:
            returns a 200 response, HTML with:
            a form, which contains:
                input fields for email and password
                "register" button -> POST /register

    POST /register
        if email or password are empty:
            returns a 400 response, with a relevant error message
        if email already exists:
            returns a 400 response, with a relevant error message
        if all is well:
            creates a user
            encrypts their password with bcrypt
            sets a cookie
            redirect -> /

    POST /login
        if email & password params match an existing user:
            sets a cookie
            redirect -> /
        if they don't match:
            returns a 401 response, HTML with a relevant error message

    POST /logout
        deletes cookie
        redirect -> /

    THE SITE HEADER:
        if a user is logged in, the header shows:
            user's email
            "My Links" link -> /urls
            logout button -> POST /logout
        if not logged in, the header shows:
            a link to the log-in page /login
            a link to the registration page /register
<file_sep>module.exports = (app) =>{
  const bcrypt = require('bcrypt');
  const users = {};                             //object that stores user info
  const urlDatabase = {};                       //objects that stores urls, grouped by user


  app.get("/", (req, res) => {
    if(users[req.session.user_id]){
      res.redirect("/urls");
    }else{
      res.redirect("/login");
    }
  });

  app.get("/urls/new", (req, res) => {          //request for the url creation page
    let templateVars = {};
    if (users[req.session["user_id"]]){
      templateVars = { username: users[req.session["user_id"]]['email']};
      res.render("urls_new", templateVars);
      return;
    }
    res.status(400).send('Sorry, you need to be logged in order to shorten an URL<br><a href="/">Go Back</a>').end();

  });


  app.get("/urls", (req, res) => {                        //list of urls created by the authenticated user
    let templateVars = {};
    if (users[req.session.user_id]){
      templateVars = { username: users[req.session["user_id"]]['email'], urls: urlDatabase[req.session["user_id"]] };
      res.render("urls_index", templateVars);
    }else{
      res.status(401).send('Please login to your account to access the URLs page.<br><a href="/login"><button>Login</button></a>').end();
    };

  });



  app.get("/urls/:id", (req, res) => {                   //request for detail and editing page
    let templateVars = {};
    let urlExistsGlobal = false;
    for(let user in urlDatabase){
      for(let url in urlDatabase[user]){
        if(url === req.params.id){
          urlExistsGlobal = true;
        }
      }
    }
    if (!users[req.session.user_id]){
      res.status(401).send('Please login to your account to access specific URL pages.<br><a href="/login"><button>Login</button></a>').end();
      return;
    }
    if(!urlExistsGlobal){
      res.status(404).send('URL was not found').end();
      return;
    }

    if(!urlDatabase[req.session.user_id][req.params.id]){
      res.status(403).send('This URL belongs to another user.<br><a href="/urls"><button>Back to URLs page</button></a>').end();
      return;
    }

    templateVars = { username: users[req.session["user_id"]]['email'], urls: urlDatabase[req.session["user_id"]], shortURL: req.params.id };
    res.render("urls_show", templateVars);
  });



  app.post("/urls", (req, res) => {              //creates a new short url for a given url and stores it in the list
    if(!users[req.session.user_id]){
      res.status(401).send('Please login to your account to create URL pages.<br><a href="/login"><button>Login</button></a>').end();
      return;
    }
    let short = generateRandomString();
    const nowDate = new Date();
    const date = nowDate.getFullYear()+'/'+(nowDate.getMonth()+1)+'/'+nowDate.getDate();
    urlDatabase[req.session.user_id][short] = {longUrl: req.body['longURL'], totalVisits: 0, uniqueVisits: 0, date: date, totalVisitsDetail: [], uniqueVisitsDetail: {}};
    res.redirect(`/urls/${short}`);
  });


  app.delete("/urls/:id/delete", (req, res) =>{     //deletes the selected entry from the list
    let urlExistsGlobal = false;
    for(let user in urlDatabase){
      for(let url in urlDatabase[user]){
        if(url === req.params.id){
          urlExistsGlobal = true;
        }
      }
    }
    if (!users[req.session.user_id]){
      res.status(401).send('Please login to your account to delete URL pages.<br><a href="/login"><button>Login</button></a>').end();
      return;
    }
    if(!urlExistsGlobal){
      res.status(404).send('URL was not found').end();
      return;
    }

    if(!urlDatabase[req.session.user_id][req.params.id]){
      res.status(403).send('This URL belongs to another user.<br><a href="/urls"><button>Back to URLs page</button></a>').end();
      return;
    }
    delete urlDatabase[req.session.user_id][req.params.id];
    res.redirect('/urls');

  });

  app.put("/urls/:id/update", (req, res) =>{     //updates the long of the select entry
    let urlExistsGlobal = false;
    for(let user in urlDatabase){
      for(let url in urlDatabase[user]){
        if(url === req.params.id){
          urlExistsGlobal = true;
        }
      }
    }
    if (!users[req.session.user_id]){
      res.status(401).send('Please login to your account to update URL pages.<br><a href="/login"><button>Login</button></a>').end();
      return;
    }
    if(!urlExistsGlobal){
      res.status(404).send('URL was not found').end();
      return;
    }

    if(!urlDatabase[req.session.user_id][req.params.id]){
      res.status(403).send('This URL belongs to another user.<br><a href="/urls"><button>Back to URLs page</button></a>').end();
      return;
    }
    urlDatabase[req.session.user_id][req.params.id]['longUrl'] = req.body['longURL'];
    res.redirect('/urls');
  });

  app.get("/u/:shortURL", (req, res) => {         //redirects the user to the respective long url, given a short url
    for(let user in urlDatabase){
      for(let url in urlDatabase[user]){
        if(url === req.params.shortURL){
          let alreadyVisited = false;
          for(let visit in urlDatabase[user][url]['uniqueVisitsDetail']){
            if(urlDatabase[user][url]['uniqueVisitsDetail'][visit]['user'] === req.session.user_id){
              alreadyVisited = true;
            }
          }
          const nowDate = new Date();
          if(!alreadyVisited){
            urlDatabase[user][url]['uniqueVisitsDetail'][req.session.user_id] = {user: req.session.user_id, timestamp: nowDate}
            urlDatabase[user][url]['uniqueVisits'] += 1;
          }
          urlDatabase[user][url]['totalVisitsDetail'].push({user: req.session.user_id, timestamp: nowDate});
          urlDatabase[user][url]['totalVisits'] += 1;
          res.redirect(urlDatabase[user][url]['longUrl']);
          return;
        }
      }
    }
    res.status(404).send('URL was not found').end();
  });

  app.post("/logout", (req, res) => {                      //user logs out
    req.session.user_id = null;
    res.redirect('/')
  });

  app.get("/register", (req, res) =>{                       //request for registration page
    if(users[req.session.user_id]){
      res.redirect('/');
      return;
    }
    res.render('register');
  });

  app.post("/register", (req, res) =>{                        //registers a new user
    if(req.body.email === '' || req.body.password === ''){
      res.status(400).send('Sorry, email or password missing!<br><a href="/register">Go Back</a>').end();
        return;
    }
    for(const user in users){
      if(users[user]['email'] === req.body.email){
        res.status(400).send('Sorry, the email is already registered!<br><a href="/register">Go Back</a>').end();
        return;
      }
    }
    let randomId = generateRandomString();
    const password = <PASSWORD>;
    const hashed_password = bcrypt.hashSync(password, 10);
    users[randomId] = {
      id: randomId,
      email: req.body.email,
      password: <PASSWORD>
    };
    req.session.user_id = randomId;
    urlDatabase[randomId] = {};
    res.redirect('/');
  });

  app.get("/login", (req, res) =>{                     //request for login page
    if(users[req.session.user_id]){
      res.redirect('/');
      return;
    }
    res.render('login');
  })

  app.post("/login", (req, res) => {                   //user authentication
    for(const user in users){
      if(users[user]['email'] === req.body.email){
        if(bcrypt.compareSync(req.body.password, users[user]['password'])){
          req.session.user_id = users[user]['id'];
          res.redirect('/');
          return;
        }else{
          res.status(401).send('Sorry, this is the wrong password for this email!<br><a href="/login">Go Back</a>').end();
          return;
        }
      }
    }
    res.status(400).send('Sorry, the email is not registered!<br><a href="/login">Go Back</a>').end();
  });

  function generateRandomString() {             //generates a random 6 digit string
  let text = "";
  const possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

  for(let i=0; i < 6; i++){
    text += possible.charAt(Math.floor(Math.random() * possible.length));
  }
  return text;
}
};
