package com.robonobo.midas.controller;
import static com.robonobo.common.util.TextUtil.*;
import static com.robonobo.common.util.TimeUtil.*;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import com.robonobo.core.api.model.Playlist;
import com.robonobo.core.api.model.User;
import com.robonobo.core.api.proto.CoreApi.PlaylistMsg;
import com.robonobo.midas.*;
import com.robonobo.midas.model.*;
@Controller
public class PlaylistController extends BaseController {
@Autowired
EventService event;
@Autowired
FacebookService facebook;
@Autowired
TwitterService twitter;
@Autowired
NotificationService notification;
@RequestMapping(value = "/playlists/{pIdStr}", method = RequestMethod.GET)
public void getPlaylist(@PathVariable("pIdStr") String pIdStr, HttpServletRequest req, HttpServletResponse resp) throws IOException {
long playlistId = Long.parseLong(pIdStr, 16);
MidasPlaylist p = midas.getPlaylistById(playlistId);
if (p == null) {
send404(req, resp);
return;
}
// Check to see if this user is allowed to see the playlist - is it public, or if not, is s/he
// the owner, or a friend of the owner?
User u = getAuthUser(req);
if (u == null) {
send401(req, resp);
return;
}
boolean allowed = p.getVisibility().equals(Playlist.VIS_ALL);
if (!allowed) {
ownerLoop: for (Long ownerId : p.getOwnerIds()) {
if (ownerId.equals(u.getUserId())) {
allowed = true;
break;
}
if (p.getVisibility().equals(Playlist.VIS_FRIENDS)) {
User owner = midas.getUserById(ownerId);
for (Long friendId : owner.getFriendIds()) {
if (u.getUserId() == friendId) {
allowed = true;
break ownerLoop;
}
}
}
}
}
if (allowed) {
log.info("Returning playlist " + playlistId + " to " + u.getEmail());
writeToOutput(p.toMsg(), resp);
} else
send401(req, resp);
}
@RequestMapping(value = "/playlists/{pIdStr}", method = RequestMethod.PUT)
@Transactional(rollbackFor = Exception.class)
public void putPlaylist(@PathVariable("pIdStr") String pIdStr, HttpServletRequest req, HttpServletResponse resp) throws IOException {
long playlistId = Long.parseLong(pIdStr, 16);
MidasUser u = getAuthUser(req);
if (u == null) {
send401(req, resp);
return;
}
MidasPlaylist currentP = (playlistId <= 0) ? null : midas.getPlaylistById(playlistId);
PlaylistMsg.Builder pBldr = PlaylistMsg.newBuilder();
readFromInput(pBldr, req);
PlaylistMsg pMsg = pBldr.build();
MidasPlaylist mp = new MidasPlaylist(pMsg);
boolean tracksAdded = false;
if (currentP == null) {
// New playlist
tracksAdded = (mp.getStreamIds().size() > 0);
mp.getOwnerIds().clear();
mp.getOwnerIds().add(u.getUserId());
mp.setUpdated(now());
mp = midas.newPlaylist(mp);
u.getPlaylistIds().add(mp.getPlaylistId());
u.setUpdated(now());
midas.saveUser(u);
writeToOutput(mp.toMsg(), resp);
log.info(u.getEmail() + " created playlist " + mp.getPlaylistId());
event.playlistCreated(u, mp);
} else {
// Existing playlist
if(mp.getTitle().equalsIgnoreCase("loves")) {
// If this is loves, handle notifications separately
tracksAdded = false;
midas.lovesChanged(u, currentP, mp);
} else if(mp.getTitle().equalsIgnoreCase("radio")) {
// Never notify radio
tracksAdded = false;
} else
tracksAdded = (mp.getStreamIds().size() > currentP.getStreamIds().size());
if (!currentP.getOwnerIds().contains(u.getUserId())) {
send401(req, resp);
return;
}
currentP.copyFrom(mp);
currentP.setUpdated(getUpdatedDate(currentP.getUpdated()));
midas.savePlaylist(currentP);
writeToOutput(currentP.toMsg(), resp);
log.info(u.getEmail() + " updated playlist " + playlistId);
event.playlistUpdated(u, currentP);
}
// Don't send notifications if tracks deleted, or for Radio
if (tracksAdded && !mp.getTitle().equalsIgnoreCase("radio"))
notification.playlistUpdated(u, mp);
}
@RequestMapping(value = "/playlists/{pIdStr}", method = RequestMethod.DELETE)
@Transactional(rollbackFor = Exception.class)
public void deletePlaylist(@PathVariable("pIdStr") String pIdStr, HttpServletRequest req, HttpServletResponse resp) throws IOException {
long playlistId = Long.parseLong(pIdStr, 16);
MidasUser u = getAuthUser(req);
MidasPlaylist p = midas.getPlaylistById(playlistId);
if (p == null)
return;
if (u == null || !p.getOwnerIds().contains(u.getUserId())) {
send401(req, resp);
return;
}
if (p.getOwnerIds().size() == 1) {
// If they were the only owner, just delete the whole thing
midas.deletePlaylist(p);
u.getPlaylistIds().remove(playlistId);
u.setUpdated(now());
midas.saveUser(u);
log.info(u.getEmail() + " deleted playlist " + playlistId);
} else {
// Otherwise, just remove them from the owner list
p.getOwnerIds().remove(u.getUserId());
p.setUpdated(getUpdatedDate(p.getUpdated()));
midas.savePlaylist(p);
u.getPlaylistIds().remove(playlistId);
u.setUpdated(now());
midas.saveUser(u);
log.info("Removed user " + u.getEmail() + " from owners of playlist " + playlistId);
}
event.playlistDeleted(u, p);
}
@RequestMapping("/playlists/{pIdStr}/post-update")
public void postPlaylistUpdate(@PathVariable("pIdStr") String pIdStr, @RequestParam("service") String service, @RequestParam(value = "msg", required = false) String msg,
HttpServletRequest req, HttpServletResponse resp) throws IOException {
long playlistId = Long.parseLong(pIdStr, 16);
Playlist p = midas.getPlaylistById(playlistId);
service = service.toLowerCase();
MidasUser u = getAuthUser(req);
if (u == null) {
send401(req, resp);
return;
}
boolean allowed = false;
if (p.getOwnerIds().contains(u.getUserId()))
allowed = true;
else if (p.getVisibility().equalsIgnoreCase("all"))
allowed = true;
else if (p.getVisibility().equalsIgnoreCase("friends")) {
for (long ownerId : p.getOwnerIds()) {
User owner = midas.getUserById(ownerId);
if (owner.getFriendIds().contains(u.getUserId())) {
allowed = true;
break;
}
}
}
if (!allowed) {
send401(req, resp);
return;
}
if (msg != null)
msg = urlDecode(msg);
MidasUserConfig muc = midas.getUserConfig(u);
if ("facebook".equals(service))
facebook.postPlaylistUpdateToFacebook(muc, p, msg);
else if ("twitter".equals(service))
twitter.postPlaylistUpdateToTwitter(muc, p, msg);
else
log.error("Error: user " + u.getEmail() + " tried to update their playlist to service: " + service);
event.playlistPosted(u, p, service);
}
}