package models;

import java.util.Date;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.ManyToOne;
import javax.persistence.Transient;

import models.Test.TestType;
import utils.StringUtil;

@Entity
public class Media extends ModelUuid implements Cloneable {
	public static enum MediaType {
		VIDEO, PHOTO, AUDIO, TEXT;

		public static MediaType tryBuildMediaTypeFromValue(String val) {
			if (StringUtil.isNil(val)) {
				return null;
			}

			for (MediaType mediaType : values()) {
				if (mediaType.name().equals(val)) {
					return mediaType;
				}
			}

			return null;
		}
	}

	@Basic
	@Enumerated(EnumType.STRING)
	private MediaType mediaType;
	
	@Basic
	@Enumerated(EnumType.STRING)
	private TestType testType;

	@Basic
	private String mediaName;

	@Basic
	private String repositoryId;

	@Basic
	private String mediaPath;

	@Basic
	private String thumbRepositoryId;

	@Basic
	private String thumbPath;

	@Basic
	@ManyToOne(cascade = { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH })
	private User mediaAuthor;

	@Basic
	private Date createdAt = new Date();

	@Transient
	public static final String CREATED_AT_DATE_FORMAT = "dd/MM/yyyy";

	@Basic
	private Boolean deleted = false;
	
	@Basic
	private Boolean isUser = false;
	

	public Boolean getIsUser() {
		return isUser;
	}

	public void setIsUser(Boolean isUser) {
		this.isUser = isUser;
	}

	public MediaType getMediaType() {
		return mediaType;
	}

	public void setMediaType(MediaType mediaType) {
		this.mediaType = mediaType;
	}

	public String getMediaName() {
		return mediaName;
	}

	public void setMediaName(String mediaName) {
		this.mediaName = mediaName;
	}

	public String getMediaPath() {
		return mediaPath;
	}

	public void setMediaPath(String mediaPath) {
		this.mediaPath = mediaPath;
	}

	public User getMediaAuthor() {
		return mediaAuthor;
	}

	public void setMediaAuthor(User mediaAuthor) {
		this.mediaAuthor = mediaAuthor;
	}

	public Date getCreatedAt() {
		return createdAt;
	}

	public void setCreatedAt(Date createdAt) {
		this.createdAt = createdAt;
	}

	public Boolean getDeleted() {
		return deleted;
	}

	public void setDeleted(Boolean deleted) {
		this.deleted = deleted;
	}

	public String getRepositoryId() {
		return repositoryId;
	}

	public void setRepositoryId(String repositoryId) {
		this.repositoryId = repositoryId;
	}

	public String getThumbPath() {
		return thumbPath;
	}

	public void setThumbPath(String thumbPath) {
		this.thumbPath = thumbPath;
	}

	public String getThumbRepositoryId() {
		return thumbRepositoryId;
	}

	public void setThumbRepositoryId(String thumbRepositoryId) {
		this.thumbRepositoryId = thumbRepositoryId;
	}

	public static List<Media> findAllFilteredByMediaTypeAndMediaNameAndMediaAuthorAndMediaDateAndMediaTestId(
			boolean isAdmin, String mediaType, String mediaName, String mediaAuthor, String mediaDate,
			String mediaTestId, String testType) {
		List<Media> ret = new LinkedList<Media>();
		if (!StringUtil.isNil(mediaTestId)) {
			List<SlideContentComponent> list = SlideContentComponent.findByTestId(mediaTestId);
			if (list != null && !list.isEmpty()) {
				for (SlideContentComponent c : list) {
					Media m = c.getMedia();
					if (m != null){
						
						ret.add(c.getMedia());
					}
				}
			}
		} else {
			boolean filtered = false;
			String query = "";
			String sep = "";
			Map<String, Object> queryParams = new LinkedHashMap<String, Object>();
			if (!StringUtil.isNil(mediaType)) {
				filtered = true;
				query += sep + "mediaType LIKE :mediaType";
				sep = " AND ";
				queryParams.put("mediaType", MediaType.valueOf(mediaType));
			}
			if (!StringUtil.isNil(mediaName)) {
				filtered = true;
				query += sep + "mediaName LIKE :mediaName";
				sep = " AND ";
				queryParams.put("mediaName", "%" + mediaName + "%");
			}
			if (!StringUtil.isNil(mediaAuthor)) {
				filtered = true;
				query += sep + "mediaAuthor.name LIKE :mediaAuthor";
				sep = " AND ";
				queryParams.put("mediaAuthor", "%" + mediaAuthor + "%");
			}
			if (!StringUtil.isNil(mediaDate)) {
				Date d = StringUtil.tryParseDate(mediaDate, null, Media.CREATED_AT_DATE_FORMAT);
				filtered = true;
				query += sep + "createdAt >= :mediaDate";
				sep = " AND ";
				queryParams.put("mediaDate", d);
			}
			
			if (!StringUtil.isNil(testType)) {
				filtered = true;
				query += sep + "testType LIKE :testType";
				sep = " AND ";
				queryParams.put("testType", TestType.valueOf(testType));
			}

			if (!filtered) {
				if (isAdmin)
					ret = Media.findAll();
				else
					ret = Media.findAllByDeleted(false);
			} else {
				if (!isAdmin) {
					query += sep + "deleted = :deleted";
					queryParams.put("deleted", false);
				}
				JPAQuery q = Media.find(query);
				for (String key : queryParams.keySet()) {
					q.setParameter(key, queryParams.get(key));
				}
				ret = q.fetch();
			}
		}
		return ret;
	}

	public static List<Media> findAllByDeleted(Boolean deleted) {
		List<Media> ret = new LinkedList<Media>();
		if (deleted == null) {
			ret = Media.findAll();
		} else {
			ret = Media.find("deleted=:deleted").setParameter("deleted", deleted).fetch();
		}
		return ret;
	}

	public static Media findByRepositoryId(String repositoryId) {
		if (StringUtil.isNil(repositoryId)) {
			return null;
		}
		Media ret = Media.find("repositoryId=:repositoryId").setParameter("repositoryId", repositoryId).first();

		return ret;
	}

	public static Media findByThumbRepositoryId(String thumbRepositoryId) {
		if (StringUtil.isNil(thumbRepositoryId)) {
			return null;
		}
		Media ret = Media.find("thumbRepositoryId=:thumbRepositoryId")
				.setParameter("thumbRepositoryId", thumbRepositoryId).first();

		return ret;
	}

	public void setTestType(TestType tt) {
		this.testType = tt;
	}

	public TestType getTestType() {
		return testType;
	}
	
}