-- args save_vote(0 file or object TEXT, 1 file/object id INT, 2 vote INT, 3 accountid INT) 
DROP FUNCTION save_vote(TEXT, INT, INT, INT);
CREATE OR REPLACE FUNCTION save_vote(TEXT, INT, INT, INT) RETURNS REAL
AS $$
  if args[0] == "file":
    vote_query = plpy.prepare("SELECT * FROM filevote WHERE fileid = $1 AND accountid = $2", ["int", "int"])
    votes = plpy.execute(vote_query, [args[1], args[3]])

    # update or insert, will be changed to single SQL when postgresql supports UPDATE OR INSERT
    if votes.nrows() > 0:
      set_vote = plpy.prepare("UPDATE filevote SET vote = $1 WHERE fileid = $2 AND accountid = $3", ["int", "int", "int"])
      plpy.execute(set_vote,[args[2], args[1], args[3]])
    else:
      set_vote = plpy.prepare("INSERT INTO filevote (vote, fileid, accountid) VALUES ($1, $2, $3)", ["int", "int", "int"])
      plpy.execute(set_vote,[args[2], args[1], args[3]])

    # updating filepoints column
    set_filepoints = plpy.prepare("SELECT update_points($1) AS point", ["int"])
    points = plpy.execute(set_filepoints, [args[1]])

    # finding whose file was voted
    get_accountid = plpy.prepare("SELECT setupaccountid AS accountid FROM file WHERE id = $1", ["int"])
    account = plpy.execute(get_accountid, [args[1]])
    accountid = account[0]["accountid"]

    # updating account avgfilevote column
    set_accountvotes = plpy.prepare("SELECT update_account_votes($1) AS avgvote", ["int"])
    avgaccount = plpy.execute(set_accountvotes, [accountid])
  
    # returning the new points sum for file
    return points[0]["point"]

  elif args[0] == "object":
    vote_query = plpy.prepare("SELECT * FROM objectvote WHERE id = $1 AND accountid = $2", ["int", "int"])
    votes = plpy.execute(vote_query, [args[1], args[3]])

    # update or insert, will be changed to single SQL when postgresql supports UPDATE OR INSERT
    if votes.nrows() > 0:
      set_vote = plpy.prepare("UPDATE objectvote SET vote = $1 WHERE id = $2 AND accountid = $3", ["int", "int", "int"])
      plpy.execute(set_vote,[args[2], args[1], args[3]])
    else:
      set_vote = plpy.prepare("INSERT INTO objectvote (vote, id, accountid) VALUES ($1, $2, $3)", ["int", "int", "int"])
      plpy.execute(set_vote,[args[2], args[1], args[3]])


    # updating voteavg column
    set_points = plpy.prepare("SELECT update_opoints($1) AS point", ["int"])
    points = plpy.execute(set_points, [args[1]])

    # returning the new points sum for file
    return points[0]["point"]

  return None
$$ LANGUAGE PlPython3u;
