<%
	import se.datadosen.util.Dates;

	void writeIndexPath(File dir, String prefix)
	{
		if( !isTopLevelFolder(dir) )
		{
			writeIndexPath(dir.getParentFile(), prefix + "../");
			out.print(TOP_BAR_PATH_SEPARATOR);
		}

		if( prefix.length()>0 )
			out.print("<a class=\"path\" href=\"" + prefix + engine.getIndexPageName() + engine.getPageExtension() + "\">");
		else
			out.print("<a class=\"path\" href=\"" + firstIndexPage + "\">");

		out.print( getDirectoryTitle(dir) );
		out.print("</a>");
	}

	String getSlideVoiceAnnotationPath(File myfile)
	{
		File sound = getOriginalVoiceAnnotationFile(myfile);

		if( sound!=null )
			return "slides/" + sound.getName();

		return null;
	}

	String getFolderVoiceAnnotationPath()
	{
		return getFolderVoiceAnnotationPath(imageDirectory);
	}

	String getFolderVoiceAnnotationPath(File dir)
	{
		File sound = getOriginalVoiceAnnotationFile(dir);

		if( sound!=null )
		{
			String soundPath;

			if( !outputDirectory.equals(imageDirectory) )
			{
				if( imageDirectory.equals(dir) )
				{
					se.datadosen.util.IO.copyFile(sound.getAbsolutePath(), outputDirectory, true);
					soundPath = sound.getName();
				}
				else
					soundPath = dir.getName() + "/" + sound.getName();
			}
			else
				soundPath = se.datadosen.util.IO.relativePath(sound, outputDirectory);

			return soundPath;
		}

		return null;
	}

	String getFolderBackgroundPath()
	{
		Map vars = getVariableContainer(imageDirectory);
		String key = CACHE_KEY_PREFIX + META_INDEX_BACKGROUND_IMAGE;

		if( !vars.containsKey(key) )
			vars.put(key, getFolderBackgroundPathImpl());

		return vars.get(key);
	}

	String getFolderBackgroundPathImpl()
	{
		File background = getBackgroundImageFile(META_INDEX_BACKGROUND_IMAGE, imageDirectory);

		if( background!=null )
		{
			String backgroundPath;

			if( !outputDirectory.equals(imageDirectory) || !isInsideAlbum(background) )
			{
				se.datadosen.util.IO.copyFile(background.getAbsolutePath(), outputDirectory, true);
				backgroundPath = background.getName();
			}
			else
				backgroundPath = se.datadosen.util.IO.relativePath(background, new File(outputDirectory.getPath()));

			return backgroundPath;
		}

		return null;
	}

	String getDirectoryInfoImpl(File dir, String info_key, String default_value, boolean tooltip)
	{
		String info_content = readUserVariableAsString(info_key, dir.getParentFile(), default_value);
		StringTokenizer st = new StringTokenizer(info_content, ",;|~");
		String result = "";

		while( st.hasMoreTokens() )
		{
			String token = st.nextToken().trim().toLowerCase();

			if( token.equals("title") )
				result = appendString(result, getDirectoryTitle(dir), tooltip);
			else if( token.equals("filename") )
				result = appendString(result, dir.getName(), tooltip);
			else if( token.equals("date") )
				result = appendString(result, getDirectoryDate(dir), tooltip);
			else if( token.equals("header") )
				result = appendString(result, getHeaderContent(dir, true), tooltip);
			else if( token.equals("footer") )
				result = appendString(result, getFooterContent(dir, true), tooltip);
			else if( token.equals("slidecount") )
				result = appendString(result, "(" + getDirectorySlideCount(dir) + " " + getFromResourceBundle("slides") +")", tooltip);
		}

		return( tooltip ? clearHtmlCode(result) : result );
	}

	String getDirectoryDate(File dir)
	{
		return Dates.format( Dates.toDate(dir.lastModified()), engine.getDateFormat() );
	}

	String getDirectoryTooltip(File dir)
	{
		Map vars = getVariableContainer(dir);

		if( !vars.containsKey(CACHE_KEY_THUMBNAIL_TOOLTIP) )
			vars.put(CACHE_KEY_THUMBNAIL_TOOLTIP, getDirectoryInfoImpl(dir, USER_VAR_FOLDER_TOOLTIP_CONTENT, DEFAULT_FOLDER_TOOLTIP_CONTENT, true));

		return vars.get(CACHE_KEY_THUMBNAIL_TOOLTIP);
	}

	String getDirectoryCaption(File dir)
	{
		return getDirectoryInfoImpl(dir, USER_VAR_FOLDER_CAPTION_CONTENT, DEFAULT_FOLDER_CAPTION_CONTENT, false);
	}
	
	String getThumbnailCaption(File myfile)
	{
		return getThumbnailInfoImpl(myfile, USER_VAR_THUMBNAIL_CAPTION_CONTENT, DEFAULT_THUMBNAIL_CAPTION_CONTENT, false);
	}

	String getHeaderContent()
	{
		return getHeaderContent(null, false);
	}

	String getHeaderContent(File dir, boolean tooltip)
	{
		Map vars = getVariableContainer(dir);
		String cache_key = CACHE_KEY_PREFIX + META_FOLDER_HEADER + tooltip;

		if( !vars.containsKey(cache_key) )
			vars.put(cache_key, getHeaderContentImpl(dir, tooltip));

		return vars.get(cache_key);
	}

	String getHeaderContentImpl(File dir, boolean tooltip)
	{
		File header_file = new File((dir!=null) ? dir : imageDirectory, "header.inc");
		String header_content = null;

		if( header_file.exists() )
			header_content = readTextFile(header_file);

		String result = appendString(header_content, readFromFolderMetadata(META_FOLDER_HEADER, dir), tooltip);

		return( tooltip ? clearHtmlCode(result) : result );
	}

	// Return the first thumbnail for simpler implementation. Later this can be improved to be really random!
	String getRandomImageName(File dir)
	{
		File[] list = dir.listFiles();
		int dif = (int)(Math.random() * list.length);

		for (int i=0; i<list.length; i++)
		{
			int tmp = (i + dif) % list.length;
		
			if( se.datadosen.util.FileFilters.isFileSupported(list[tmp]) )
				return list[tmp].getName();
		}

		return null;
	}

	Object[] getFolderIconInformation(File dir)
	{
		String folder_icon = readFromFolderMetadata(META_FOLDER_ICON, dir);
		String icon_set_path = getIconSetPath(dir.getParentFile());
		Dimension icon_size = null;
		boolean is_thumbnail = false;

		if( isEmptyString(folder_icon) )
		{
			String rand_image = null;

			if( isVariableValueEqual( USER_VAR_CHOOSE_RANDOM_ICON_FOR_FOLDER, dir.getParentFile(), true ) )
				rand_image = getRandomImageName(dir);

			if( isEmptyString(rand_image) )
			{
				folder_icon = icon_set_path + "/folder.gif";
				icon_size = getIconDimension(new File(outputDirectory, folder_icon), maxThumbWidth, maxThumbHeight);
			}
			else
			{
				folder_icon = dir.getName() + "/thumbs/" + rand_image;
				if( isFixedShapeFilterAppliedOnThumbnails() )
					icon_size = new Dimension(maxThumbWidth, maxThumbHeight);
				else
					icon_size = getIconDimension(new File(dir, rand_image), maxThumbWidth, maxThumbHeight);
				is_thumbnail = true;
			}
		}
		else
		{
			File src_file = new File(dir, folder_icon);
			boolean has_thumbnail = false;
			boolean inside_album = false;
			
			if( !src_file.exists() )
				displayMessage( "The specified folder icon '" + folder_icon + "' does not exist!" );
			else
			{
				has_thumbnail = hasGotThumbnail(src_file);
				inside_album = isInsideAlbum(src_file);
			}

			if( has_thumbnail && inside_album )
			{	// Using the thumbnail if the folder's image has got any!
				if( isFixedShapeFilterAppliedOnThumbnails() )
					icon_size = new Dimension(maxThumbWidth, maxThumbHeight);
				else
					icon_size = getIconDimension(src_file, maxThumbWidth, maxThumbHeight);

				src_file = new File(src_file.getParentFile() + "/thumbs/", src_file.getName());
				folder_icon = se.datadosen.util.IO.relativePath(src_file, imageDirectory);
				is_thumbnail = true;
			}
			else
			{
				src_file = new File(imageDirectory, dir.getName() + "/" + folder_icon);

				if( !outputDirectory.equals(imageDirectory) && src_file.exists() )
				{
					File dest_dir = new File(outputDirectory, dir.getName());

					dest_dir.mkdirs();
					se.datadosen.util.IO.copyFile(src_file.getAbsolutePath(), dest_dir, true);
				}

				folder_icon = dir.getName() + "/" + src_file.getName();
				icon_size = getIconDimension(src_file, maxThumbWidth, maxThumbHeight);
			}
		}

		// JAlbum doesn't deal correctly with GIF images! It just store their thumbnail & slide images as JPG so have to do some checkings here...
		if( is_thumbnail && folder_icon!=null )
			folder_icon = convertImageNameToJPG(folder_icon);

		Object[] result = new Object[3];

		result[0] = folder_icon;
		result[1] = getAddMiniFolderSign(dir) ? icon_set_path + "/folder_small.gif" : null;
		result[2] = icon_size;
		return result;
	}
	
	boolean getAddMiniFolderSign(File dir)
	{
		String folder_icon = readFromFolderMetadata(META_FOLDER_ICON, dir);

		if( isEmptyString(folder_icon) )
			return( isVariableValueEqual( USER_VAR_CHOOSE_RANDOM_ICON_FOR_FOLDER, dir.getParentFile(), true ) && getRandomImageName(dir)!=null );
		else
			return true;
	}

	boolean hasGotThumbnail(File file)
	{
		File dir = file.getParentFile();
		File[] files = engine.listFiles(dir, false, null);

		for( int i=0; i<files.length; i++ )
		{
			if( files[i].equals(file) )
				return true;
		}
		
		return false;
	}
	
	// Generate drop box options for quick navigation
	void writeIndexJumpingMenuItems()
	{
		String template = getIndexJumpingMenuItems();
        int dirTotalIndexes = (totalIndexes!=void) ? totalIndexes : 1;
		Object[] args = new Object[dirTotalIndexes];

		if (indexNum == void)
			indexNum = 1;
		for( int i=0; i<dirTotalIndexes; i++ )
		{
			if( i==indexNum-1 )
				args[i] = "selected=\"selected\"";
			else
				args[i] = "";
		}
		out.println( formatBigTemplate(template, args) );
	}

	String getIndexJumpingMenuItems()
	{
		Map vars = getVariableContainer(imageDirectory);

		if( !vars.containsKey(CACHE_KEY_INDEX_JUMP_TO_PAGE) )
			vars.put(CACHE_KEY_INDEX_JUMP_TO_PAGE, getIndexJumpingMenuItemsImpl());

		return vars.get(CACHE_KEY_INDEX_JUMP_TO_PAGE);
	}

	String getIndexJumpingMenuItemsImpl()
	{
		// Make links to sibling directories
		StringBuffer buffer = new StringBuffer();
		File parentDir = imageDirectory.getParentFile();
		String template = "<option value=\"{0}\" {1}>{2}</option>\n";
		Object[] args = new Object[3];

		if( isInsideAlbum(parentDir) )
		{
			File[] files = engine.listFiles(parentDir, true, programDirectory);

			for( int i=0; i<files.length; i++ )
			{
				if( !files[i].isDirectory() )
					continue;

				args[0] = "../" + encodeUrlIfNecessary(files[i].getName()) + "/" + engine.getIndexPageName() + engine.getPageExtension();
				if( files[i].equals(imageDirectory) )
				{
					args[1] = (totalIndexes==void) ? "selected=\"selected\"" : "";
					args[2] = "- " + getDirectoryTitle(files[i]);
				}
				else
				{
					args[1] = "";
					args[2] = "+ " + getDirectoryTitle(files[i]);
				}

				buffer.append( MessageFormat.format(template, args) );
				if( files[i].equals(imageDirectory) && totalIndexes!=void )
					writeIndexCurrentFolderPages(buffer, JUMPING_MENU_HIERARCHY_SEPARATOR + "- ");
			}
		}
		else
			writeIndexCurrentFolderPages(buffer, "- ");

		return buffer.toString();
	}

	void writeIndexCurrentFolderPages(StringBuffer buffer, String prefix)
	{
		String template = "<option value=\"{0}\" {1}>" + prefix + getFromResourceBundle("page") + " {2}</option>\n";
        int dirTotalIndexes = (totalIndexes!=void) ? totalIndexes : 1;
		Object[] args = new Object[3];

		if (indexNum == void)
			indexNum = 1;

		for (int i=1; i<=dirTotalIndexes; i++)
		{
			args[0] = engine.getIndexPageName() + (i==1 ? "" : i) + engine.getPageExtension();
			args[1] = "{" + (i-1) + "}";
			args[2] = "" + i;

			buffer.append( MessageFormat.format(template, args) );
		}
	}

	int getDirectorySlideCount(File dir)
	{
		Map vars = getVariableContainer(dir);

		if( !vars.containsKey(CACHE_KEY_DIRECTORY_SLIDE_COUNT) )
			vars.put(CACHE_KEY_DIRECTORY_SLIDE_COUNT, new Integer(engine.countFiles(dir)));

		return vars.get(CACHE_KEY_DIRECTORY_SLIDE_COUNT).intValue();
	}

	String[] writeFolderThumbnail(File dir)
	{
		Map vars = (Map)fileVariables.get(dir);
		String tooltip = getDirectoryTooltip(dir);
		int border_size = getFolderThumbnailBorderSize(dir.getParentFile());
		String border_color = shouldAddColorToFolderThumbnailBorder(dir.getParentFile()) ? getFolderThumbnailBorderColor(dir.getParentFile()) : null;
		String border_rsc_path = getFolderThumbnailBorderResourcePath(dir.getParentFile());
		String link_path = vars.get("closeupPath");
		Object[] folder_icon_info = getFolderIconInformation(dir);
		String frame_block;

		if( folder_icon_info[1]!=null )
			frame_block = getFrameBlock((String)folder_icon_info[0], link_path, false, tooltip, (Dimension)folder_icon_info[2], border_rsc_path, border_size, border_color, false, true, (String)folder_icon_info[1]);
		else
		{
			String imageExtraParameters = ("width=\"" + ((Dimension)folder_icon_info[2]).width + "\" height=\"" + ((Dimension)folder_icon_info[2]).height + "\"");

			frame_block = getActionBlock(link_path, null, tooltip, folder_icon_info[0].toString(), imageExtraParameters);
		}

		out.println( frame_block );

		String[] props = new String[4];

		props[0] = link_path;
		props[1] = getDirectoryCaption(dir);
		props[2] = getFolderVoiceAnnotationPath(dir);
		props[3] = "TYPE_FOLDER";
		return props;
	}

	String[] writeSlideThumbnail(File myfile)
	{
		Map vars = (Map)fileVariables.get(myfile);
		boolean isMovie = isMovieFile(myfile);
		Dimension display_size = new Dimension(maxThumbWidth, maxThumbHeight);
		String tooltip = getThumbnailTooltip(myfile);
		int border_size = getSlideThumbnailBorderSize(myfile);
		String border_color = shouldAddColorToSlideThumbnailBorder(myfile) ? getSlideThumbnailBorderColor(myfile) : null;
		String border_rsc_path = getSlideThumbnailBorderResourcePath(myfile);
		String link_path;
		String display_path;
		String mini_sign = null;
		boolean apply_size_on_display = true;
		
		if( isMovie )
		{
			link_path = "slides/" + vars.get("label") + engine.getPageExtension();

			File thumbnail = getMovieThumbnailFile(myfile);
			String icon_set_path = getIconSetPath(myfile);
			File destDir;

			if( thumbnail==null )
			{
				display_path = icon_set_path + "/movie.gif";
				apply_size_on_display = false;
			}
			else
			{
				destDir = new File(outputDirectory.getPath(), "thumbs/");
				destDir.mkdirs();
				
				se.datadosen.util.IO.copyFile(thumbnail.getAbsolutePath(), destDir, true);
				display_path = "thumbs/" + thumbnail.getName();

				display_size = getIconDimension(thumbnail, maxThumbWidth, maxThumbHeight);
				mini_sign = icon_set_path + "/movie_small.gif";
			}
			
			// JAlbum itself doesn't do a good job on copying the movies because of the following 
			// reasons so doing it manually:
			//   - Copying the movies into the root of the destination folder (instead of "slides")
			//     which causes problems when playing them with WMP (it doesn't support playing from 
			//     any other folder than the current because of the security reasons).
			//   - It does not copy the movies when "Copy Originals" is not checked (but they're
			//     always needed regardless of status of this option).
			destDir = new File(outputDirectory.getPath(), "slides/");
			destDir.mkdirs();
			se.datadosen.util.IO.copyFile(myfile.getAbsolutePath(), destDir, true);
		}
		else
		{
			link_path = vars.get("closeupPath");
			display_path = vars.get("thumbPath");

			if( isFixedShapeFilterAppliedOnThumbnails() )
			{
				// Fixed shape filter applied! So we should go for the maximum thumbnail dimensions
				display_size.width = vars.get("maxThumbWidth");
				display_size.height = vars.get("maxThumbHeight");
			}
			else
			{
				display_size.width = vars.get("thumbWidth");
				display_size.height = vars.get("thumbHeight");
			}
		}

		String frame_block = getFrameBlock(display_path, link_path, false, tooltip, display_size, border_rsc_path, border_size, border_color, false, apply_size_on_display, mini_sign);

		out.println( frame_block );

		String[] props = new String[4];
		
		props[0] = link_path;
		props[1] = getThumbnailCaption(myfile);
		props[2] = getSlideVoiceAnnotationPath(myfile);
		props[3] = "TYPE_SLIDE";
		return props;
	}
	
	void writeCurrentIndexNavigationBar()
	{
		String iconSetPath = getIconSetPath(imageDirectory);

		if( totalIndexes!=void )
		{
			if( previousIndexPage!=void )
			{
				if( isVariableValueEqual( USER_VAR_INCLUDE_FIRST_LAST_PAGE_ACTIONS, imageDirectory, true ) )
					out.println( getActionBlock(firstIndexPage, "$text.first-page", iconSetPath + "/first.gif") );
				out.println( getActionBlock(previousIndexPage, "$text.prev-page", iconSetPath + "/previous.gif") );
			}
			else
			{
				if( isVariableValueEqual( USER_VAR_INCLUDE_FIRST_LAST_PAGE_ACTIONS, imageDirectory, true ) )
					out.println( getActionBlock(null, "$text.on-first-page", iconSetPath + "/first_disabled.gif") );
				out.println( getActionBlock(null, "$text.on-first-page", iconSetPath + "/previous_disabled.gif") );
			}

			out.println( NAVIGATION_BAR_SEPARATOR );
		}

		if( parentIndexPage!=void )
			out.println( getActionBlock(parentIndexPage, "$text.up", iconSetPath + "/up.gif") );

		if( totalIndexes!=void )
		{
			out.println( NAVIGATION_BAR_SEPARATOR );

			if( nextIndexPage!=void )
			{
				out.println( getActionBlock(nextIndexPage, "$text.next-page", iconSetPath + "/next.gif") );

				if( isVariableValueEqual( USER_VAR_INCLUDE_FIRST_LAST_PAGE_ACTIONS, imageDirectory, true ) )
					out.println( getActionBlock(lastIndexPage, "$text.last-page", iconSetPath + "/last.gif") );
			}
			else
			{
				out.println( getActionBlock(null, "$text.on-last-page", iconSetPath + "/next_disabled.gif") );

				if( isVariableValueEqual( USER_VAR_INCLUDE_FIRST_LAST_PAGE_ACTIONS, imageDirectory, true ) )
					out.println( getActionBlock(null, "$text.on-last-page", iconSetPath + "/last_disabled.gif") );
			}
		}
	}

    File getCurrentFile()
    {
        Iterator it = fileVariables.entrySet().iterator();

        while( it.hasNext() )
        {
            Map.Entry entry = (Map.Entry)it.next();

            if( entry.getValue()==current )
                return (File) entry.getKey();
        }

        return null;
    }
%>
