package org.kar.karusic.api;

import java.io.InputStream;
import java.util.List;

import org.bson.types.ObjectId;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataParam;
import org.kar.archidata.annotation.AsyncType;
import org.kar.archidata.dataAccess.DBAccess;
import org.kar.archidata.dataAccess.DataAccess;
import org.kar.archidata.dataAccess.addOnSQL.AddOnDataJson;
import org.kar.archidata.dataAccess.options.CheckFunction;
import org.kar.archidata.tools.DataTools;
import org.kar.karusic.model.Playlist;
import org.kar.karusic.model.Track.TrackChecker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import jakarta.annotation.security.RolesAllowed;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.DELETE;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.PATCH;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;

@Path("/playlist")
@Produces({ MediaType.APPLICATION_JSON })
public class PlaylistResource {
	private static final Logger LOGGER = LoggerFactory.getLogger(PlaylistResource.class);
	static final TrackChecker CHECKER = new TrackChecker();

	@GET
	@Path("{id}")
	@RolesAllowed("USER")
	public Playlist get(@PathParam("id") final Long id) throws Exception {
		return DataAccess.get(Playlist.class, id);
	}

	@GET
	@RolesAllowed("USER")
	public List<Playlist> gets() throws Exception {
		return DataAccess.gets(Playlist.class);
	}

	@POST
	@RolesAllowed("ADMIN")
	@Consumes(MediaType.APPLICATION_JSON)
	public Playlist post(final Playlist data) throws Exception {
		return DataAccess.insert(data, new CheckFunction(CHECKER));
	}

	@PATCH
	@Path("{id}")
	@RolesAllowed("ADMIN")
	@Consumes(MediaType.APPLICATION_JSON)
	public Playlist patch(@PathParam("id") final Long id, @AsyncType(Playlist.class) final String jsonRequest) throws Exception {
		DataAccess.updateWithJson(Playlist.class, id, jsonRequest, new CheckFunction(CHECKER));
		return DataAccess.get(Playlist.class, id);
	}

	@DELETE
	@Path("{id}")
	@RolesAllowed("ADMIN")
	public void remove(@PathParam("id") final Long id) throws Exception {
		DataAccess.delete(Playlist.class, id);
	}

	@POST
	@Path("{id}/track/{trackId}")
	@RolesAllowed("ADMIN")
	@Consumes({ MediaType.MULTIPART_FORM_DATA })
	public Playlist addTrack(@PathParam("id") final Long id, @PathParam("trackId") final Long trackId) throws Exception {
		try (DBAccess db = DBAccess.createInterface()) {
			AddOnDataJson.removeLink(db, Playlist.class, "id", id, "track", trackId);
			return db.get(Playlist.class, id);
		}
	}

	@DELETE
	@Path("{id}/track/{trackId}")
	@RolesAllowed("ADMIN")
	public Playlist removeTrack(@PathParam("id") final Long id, @PathParam("trackId") final Long trackId) throws Exception {
		try (DBAccess db = DBAccess.createInterface()) {
			AddOnDataJson.removeLink(db, Playlist.class, "id", id, "track", trackId);
			return db.get(Playlist.class, id);
		}
	}

	@POST
	@Path("{id}/cover")
	@RolesAllowed("ADMIN")
	@Consumes({ MediaType.MULTIPART_FORM_DATA })
	@AsyncType(Playlist.class)
	public void uploadCover(@PathParam("id") final Long id, @FormDataParam("file") final InputStream fileInputStream, @FormDataParam("file") final FormDataContentDisposition fileMetaData)
			throws Exception {
		try (DBAccess db = DBAccess.createInterface()) {
			DataTools.uploadCover(db, Playlist.class, id, fileInputStream, fileMetaData);
		}
	}

	@DELETE
	@Path("{id}/cover/{coverId}")
	@RolesAllowed("ADMIN")
	public Playlist removeCover(@PathParam("id") final Long id, @PathParam("coverId") final ObjectId coverId) throws Exception {
		try (DBAccess db = DBAccess.createInterface()) {
			AddOnDataJson.removeLink(db, Playlist.class, "id", id, "covers", coverId);
			return DataAccess.get(Playlist.class, id);
		}
	}
}
