package org.jerrymouse.cc.site.web;

import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLEncoder;
import java.util.List;

import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.core.Response.ResponseBuilder;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.jerrymouse.cc.site.bean.Device;
import org.jerrymouse.cc.site.bean.Format;
import org.jerrymouse.cc.site.bean.Resource;
import org.jerrymouse.cc.site.bean.Type;
import org.jerrymouse.cc.site.bean.User;
import org.jerrymouse.cc.site.database.UserDao;
import org.jerrymouse.cc.site.view.CommonViewer;
import org.jerrymouse.cc.site.web.exception.NoResourceException;
import org.jerrymouse.cc.site.web.exception.NoUserException;
import org.jerrymouse.cc.site.web.spider.WebResource;
import org.jerrymouse.cc.site.web.utils.CCRequestContext;
import org.jerrymouse.cc.site.web.utils.WebUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

//
@Path("{username}/storage/{filename}")
@Component
public class ResourceWeb {
	@Autowired
	private UserDao userDao;

	Resource resource;

	@GET
	@Path("/view")
	public Response viewResource(@PathParam("username") String username,
			@PathParam("filename") String filename,
			@QueryParam(value = "url") String url, @Context UriInfo uriInfo) {
		String u = uriInfo.getBaseUri().toString();
		WebUtil.urlBase = u.substring(0, u.lastIndexOf("user") - 1);
		try {
			creatResource(username, filename, url);
		} catch (NoResourceException e) {
			return Response.status(404).build();
		} catch (NoUserException e) {
			return Response.status(404).build();
		}
		CommonViewer viewer = new CommonViewer();
		return viewer.view(resource).build();
	}

	private void creatResource(String username, String filename, String url)
			throws NoResourceException, NoUserException {
		User user = userDao.getUserByName(username);
		if (user == null) {
			throw new NoUserException();
		}
		if (filename != null) {
			filename = new Type().removeSuffix(filename);
			resource = user.getStorage().getResourceByName(filename);
			if (resource == null && url == null) {
				throw new NoResourceException();
			}
		}
		if (url != null) {
			WebResource webResource = new WebResource(url);
			resource = new Resource(user, webResource.getName(), webResource
					.getType());
			if (filename != null)
				resource.setFilename(filename);
			user.getStorage().addResource(resource);
			resource.putBytes(webResource.getBytes());
			userDao.put(user);
		}
	}

	@GET
	public Response getResource(@PathParam("username") String username,
			@PathParam("filename") String filename,
			@HeaderParam("USER-AGENT") String userAgent,
			@QueryParam(value = "type") String type,
			@QueryParam(value = "device") String device,
			@QueryParam(value = "url") String url) {
		// error check11
		try {
			creatResource(username, filename, url);
		} catch (NoResourceException e) {
			return Response.status(404).build();
		} catch (NoUserException e) {
			return Response.status(404).build();
		}

		if (device != null) {
			resource.setFormat(new Device(device).toFormat(resource
					.getOrgType()));
		}
		if (type != null) {
			resource.setFormat(new Format(new Type(type)));
		}
		if (resource.getFormat() == null) {
			resource.setFormat(new Format(resource.getOrgType()));
		}
		ResponseBuilder responseBuilder = Response.ok();
		responseBuilder.type(resource.getFormat().getType().getMime());
		try {
			String fn = new String(resource.getFilename().getBytes("UTF-8"),
					"iso-8859-1");
			if (userAgent != null && userAgent.startsWith("MSIE")) {
				fn = URLEncoder.encode(resource.getFilename(), "utf-8");
			}
			responseBuilder.header(WebUtil.CONTENTDISPOSITION,
					WebUtil.ATTACHMENT + ";filename="
							+ resource.getFormat().getType().addSuffix(fn));
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		responseBuilder.entity(resource.getBytes());
		return responseBuilder.build();
	}

	@POST
	public Response putResource(@PathParam("username") String username,
			@PathParam("filename") String filename,
			@QueryParam(value = "url") String url) {
		User user = userDao.getUserByName(username);
		if (user == null) {
			return Response.status(404).build();
		}
		WebResource webResourceBuilder = new WebResource(url);
		if (filename == null) {
			filename = webResourceBuilder.getName();
		}
		Resource resource = new Resource(user, filename, webResourceBuilder
				.getType());
		user.getStorage().addResource(resource);
		resource.putBytes(webResourceBuilder.getBytes());
		userDao.put(user);
		return Response.ok().build();
	}

	@SuppressWarnings("unchecked")
	@POST
	@Consumes( { "multipart/form-data" })
	public Response putResource(@PathParam("username") String username,
			@PathParam("filename") String filename, byte[] data,
			@Context HttpHeaders httpHeaders) {
		User user = userDao.getUserByName(username);
		if (user == null) {
			return Response.status(404).build();
		}
		ServletFileUpload upload = new ServletFileUpload(
				new DiskFileItemFactory());
		byte[] bytes = null;
		String uploadFilename = null;
		try {
			List<FileItem> list = upload.parseRequest(new CCRequestContext(
					data, httpHeaders));
			for (FileItem item : list) {
				if (!item.isFormField()) {
					bytes = item.get();
					uploadFilename = item.getName();
				}
			}
		} catch (FileUploadException e) {
			e.printStackTrace();
		}

		resource = new Resource();
		user.getStorage().addResource(resource);
		resource.setUser(user);
		if (filename != null) {
			resource.setFilename(filename);
			Type type = new Type();
			type.removeSuffix(uploadFilename);
			resource.setOrgType(type);
		} else {
			resource.setOrgFullFilename(uploadFilename);
		}
		resource.putBytes(bytes);
		userDao.put(user);
		return Response.ok().build();
	}
}
