package com.redfin.sitemapgenerator;

import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;

/** One configurable Google Video Search URL.
  
To configure, use {@link Options}
 
*
 
* @author Dan Fabulich
 
* @see Options
 
* @see<a href="http://www.google.com/support/webmasters/bin/answer.py?answer=80472">Creating Video Sitemaps</a>
 
*/

public class GoogleVideoSitemapUrl extends WebSitemapUrl {

	
private final URL playerUrl;
	
private final URL contentUrl;
	
private final URL thumbnailUrl;
	
private final String title;
	
private final String description;
	
private final Double rating;
	
private final Integer viewCount;
	
private final Date publicationDate;
	
private final ArrayList<String> tags;
	
private final String category;
	
// TODO can there be multiple categories?
	
// "Usually a video will belong to a single category."
	
//
 
http://www.google.com/support/webmasters/bin/answer.py?answer=80472
	
private final String familyFriendly;
	
private final Integer durationInSeconds;
	
private final String allowEmbed;
	

	
/** Options to configure Google Video URLs */
	
public static class Options extends AbstractSitemapUrlOptions<GoogleVideoSitemapUrl, Options> {
		
private URL playerUrl;
		
private URL contentUrl;
		
private URL thumbnailUrl;
		
private String title;
		
private String description;
		
private Double rating;
		
private Integer viewCount;
		
private Date publicationDate;
		
private ArrayList<String> tags;
		
private String category;
		
// TODO can there be multiple categories?
		
// "Usually a video will belong to a single category."
		
//
 
http://www.google.com/support/webmasters/bin/answer.py?answer=80472
		
private Boolean familyFriendly;
		
private Integer durationInSeconds;
		
private Boolean allowEmbed;
	

		
/** Specifies a landing page URL, together with a "player" (e.g. SWF)
		 
*
  

		 
* @param url the landing page URL
		 
* @param playerUrl the URL of the "player" (e.g. SWF file)
		 
* @param allowEmbed when specifying a player, you must specify whether embedding is allowed
		 
*/

		
public Options(URL url, URL playerUrl, boolean allowEmbed) {
			
super(url, GoogleVideoSitemapUrl.class);
			
this.playerUrl = playerUrl;
			
this.allowEmbed = allowEmbed;
		
}
		

		
/** Specifies a landing page URL, together with the URL of the underlying video (e.g. FLV)
		 
*
 

		 
* @param url the landing page URL
		 
* @param contentUrl the URL of the underlying video (e.g. FLV)
		 
*/

		
public Options(URL url, URL contentUrl) {
			
super(url, GoogleVideoSitemapUrl.class);
			
this.contentUrl = contentUrl;
		
}
		

		
/** Specifies a player URL (e.g. SWF)
		 
*
  

		 
* @param playerUrl the URL of the "player" (e.g. SWF file)
		 
* @param allowEmbed when specifying a player, you must specify whether embedding is allowed
		 
*/

		
public Options playerUrl(URL playerUrl, boolean allowEmbed) {
			
this.playerUrl = playerUrl;
			
this.allowEmbed = allowEmbed;
			
return this;
		
}
		

		
/** Specifies the URL of the underlying video (e.g FLV) */
		
public Options contentUrl(URL contentUrl) {
			
this.contentUrl = contentUrl;
			
return this;
		
}
		

		
/**
		 
* A URL pointing to the URL for the video thumbnail image file. This
		 
* allows you to suggest the thumbnail you want displayed in search
		 
* results. If you provide a {@link #contentUrl(URL)}, Google will attempt
		 
* to generate a set of representative thumbnail images from your actual
		 
* video content. However, we strongly recommended that you provide a
		 
* thumbnail URL to increase the likelihood of your video being included
		 
* in the video index.
		 
*/

		
public Options thumbnailUrl(URL thumbnailUrl) {
			
this.thumbnailUrl = thumbnailUrl;
			
return this;
		
}
		

		
/** The title of the video. Limited to 100 characters. */
		
public Options title(String title) {
			
if (title != null) {
				
if (title.length() > 100) {
					
throw new RuntimeException("Video title is limited to 100 characters: " + title);
				
}
			
}
			
this.title = title;
			
return this;
		
}
		

		
/** The description of the video. Descriptions longer than 2048 characters will be truncated. */
		
public Options description(String description) {
			
if (description != null) {
				
if (description.length() > 2048) {
					
throw new RuntimeException("Truncate video descriptions to 2048 characters: " + description);
				
}
			
}
			
this.description = description;
			
return this;
		
}
		

		
/** The rating of the video. The value must be number in the range 0.0-5.0. */
		
public Options rating(Double rating) {
			
if (rating != null) {
				
if (rating < 0 || rating > 5.0) {
					
throw new RuntimeException("Rating must be between 0.0 and 5.0:" + rating);
				
}
			
}
			
this.rating = rating;
			
return this;
		
}
		

		
/** The number of times the video has been viewed */
		
public Options viewCount(int viewCount) {
			
this.viewCount = viewCount;
			
return this;
		
}
		

		
/** The date the video was first published, in {@link W3CDateFormat}. */
		
public Options publicationDate(Date publicationDate) {
			
this.publicationDate = publicationDate;
			
return this;
		
}
		

		
/**
		 
* Tag associated with the video; tags are generally very short
		 
* descriptions of key concepts associated with a video or piece of
		 
* content. A single video could have several tags, although it might
		 
* belong to only one category. For example, a video about grilling food
		 
* may belong in the Grilling category, but could be tagged "steak",
		 
* "meat", "summer", and "outdoor". Create a new <video:tag> element for
		 
* each tag associated with a video. A maximum of 32 tags is permitted.
		 
*/

		
public Options tags(ArrayList<String> tags) {
			
this.tags = tags;
			
return this;
		
}
		

		
/**
		 
* Tag associated with the video; tags are generally very short
		 
* descriptions of key concepts associated with a video or piece of
		 
* content. A single video could have several tags, although it might
		 
* belong to only one category. For example, a video about grilling food
		 
* may belong in the Grilling category, but could be tagged "steak",
		 
* "meat", "summer", and "outdoor". Create a new <video:tag> element for
		 
* each tag associated with a video. A maximum of 32 tags is permitted.
		 
*/

		
public Options tags(Iterable<String> tags) {
			
this.tags = new ArrayList<String>();
			
for (String tag : tags) {
				
this.tags.add(tag);
			
}
			
return this;
		
}
		

		
/**
		 
* Tag associated with the video; tags are generally very short
		 
* descriptions of key concepts associated with a video or piece of
		 
* content. A single video could have several tags, although it might
		 
* belong to only one category. For example, a video about grilling food
		 
* may belong in the Grilling category, but could be tagged "steak",
		 
* "meat", "summer", and "outdoor". Create a new <video:tag> element for
		 
* each tag associated with a video. A maximum of 32 tags is permitted.
		 
*/

		
public Options tags(String... tags) {
			
return tags(Arrays.asList(tags));
		
}
		

		
/**
		 
* The video's category; for example, <code>cooking</code>. The value
		 
* should be a string no longer than 256 characters. In general,
		 
* categories are broad groupings of content by subject. Usually a video
		 
* will belong to a single category. For example, a site about cooking
		 
* could have categories for Broiling, Baking, and Grilling
		 
*/

		
public Options category(String category) {
			
if (category != null) {
				
if (category.length() > 256) {
					
throw new RuntimeException("Video category is limited to 256 characters: " + title);
				
}
			
}
			
this.category = category;
			
return this;
		
}
		

		
/** Whether the video is suitable for viewing by children */
		
public Options familyFriendly(boolean familyFriendly) {
			
this.familyFriendly = familyFriendly;
			
return this;
		
}
		

		
/** The duration of the video in seconds; value must be between 0 and 28800 (8 hours). */
		
public Options durationInSeconds(int durationInSeconds) {
			
if (durationInSeconds < 0 || durationInSeconds > 28800) {
				
throw new RuntimeException("Duration must be between 0 and 28800 (8 hours):" + durationInSeconds);
			
}
			
this.durationInSeconds = durationInSeconds;
			
return this;
		
}
		

	
}

	
/** Specifies a landing page URL, together with a "player" (e.g. SWF)
	 
*
  

	 
* @param url the landing page URL
	 
* @param playerUrl the URL of the "player" (e.g. SWF file)
	 
* @param allowEmbed when specifying a player, you must specify whether embedding is allowed
	 
*/

	
public GoogleVideoSitemapUrl(URL url, URL playerUrl, boolean allowEmbed) {
		
this(new Options(url, playerUrl, allowEmbed));
	
}
	

	
/** Specifies a landing page URL, together with the URL of the underlying video (e.g. FLV)
	 
*
 

	 
* @param url the landing page URL
	 
* @param contentUrl the URL of the underlying video (e.g. FLV)
	 
*/

	
public GoogleVideoSitemapUrl(URL url, URL contentUrl) {
		
this(new Options(url, contentUrl));
	
}
	

	
/** Configures the url with options */
	
public GoogleVideoSitemapUrl(Options options) {
		
super(options);
		
contentUrl = options.contentUrl;
		
playerUrl = options.playerUrl;
		
if (playerUrl == null && contentUrl == null) {
			
throw new RuntimeException("You must specify either contentUrl or playerUrl or both; neither were specified");
		
}
		
allowEmbed = convertBooleanToYesOrNo(options.allowEmbed);
		
if (playerUrl != null && allowEmbed == null) {
			
throw new RuntimeException("allowEmbed must be specified if playerUrl is specified");
		
}
		
category = options.category;
		

		
description = options.description;
		
durationInSeconds = options.durationInSeconds;
		
familyFriendly = convertBooleanToYesOrNo(options.familyFriendly);
		

		
publicationDate = options.publicationDate;
		
rating = options.rating;
		
tags = options.tags;
		
if (tags != null && tags.size() > 32) {
			
throw new RuntimeException("A maximum of 32 tags is permitted");
		
}
		
thumbnailUrl = options.thumbnailUrl;
		
title = options.title;
		
viewCount = options.viewCount;
	
}
	

	
private static String convertBooleanToYesOrNo(Boolean value) {
		
if (value == null) return null;
		
return value ? "Yes" : "No";
	
}
	

	

	
/** Retrieves the {@link Options#playerUrl}*/
	
public URL getPlayerUrl() {
		
return playerUrl;
	
}
	

	
/** Retrieves the {@link Options#contentUrl}*/
	
public URL getContentUrl() {
		
return contentUrl;
	
}

	
/** Retrieves the {@link Options#thumbnailUrl}*/
	
public URL getThumbnailUrl() {
		
return thumbnailUrl;
	
}

	
/** Retrieves the {@link Options#title}*/
	
public String getTitle() {
		
return title;
	
}

	
/** Retrieves the {@link Options#description}*/
	
public String getDescription() {
		
return description;
	
}

	
/** Retrieves the {@link Options#rating}*/
	
public Double getRating() {
		
return rating;
	
}

	
/** Retrieves the {@link Options#viewCount}*/
	
public Integer getViewCount() {
		
return viewCount;
	
}

	
/** Retrieves the {@link Options#publicationDate}*/
	
public Date getPublicationDate() {
		
return publicationDate;
	
}

	
/** Retrieves the {@link Options#tags}*/
	
public ArrayList<String> getTags() {
		
return tags;
	
}

	
/** Retrieves the {@link Options#category}*/
	
public String getCategory() {
		
return category;
	
}

	
/** Retrieves whether the video is {@link Options#familyFriendly}*/
	
public String getFamilyFriendly() {
		
return familyFriendly;
	
}

	
/** Retrieves the {@link Options#durationInSeconds}*/
	
public Integer getDurationInSeconds() {
		
return durationInSeconds;
	
}

	
/** Retrieves whether embedding is allowed */
	
public String getAllowEmbed() {
		
return allowEmbed;
	
}





}