import java.io.*;
        import java.awt.*;
        import java.util.*;
        import java.text.*;
        import se.datadosen.jalbum.*;
        import se.datadosen.util.*;

public class Utils extends CompiledScript {

  // from makeThumbLinks();
  int numberOfMiniThumbs;
  String thumbStyle;
  boolean portraitMode;
  boolean sameSizeFilterIndex;
  int miniThumbAdjust;
  // from makeNavElement();
  String portraitModeLinefeed;
  String buttonSetPath;
  boolean slideShowContinuous;
  String firstPage;
  String lastPage;
  String indexPage;
  // from imageCalc ();
  // double polaroidStretchFactor;
  int imagePaddingAdjust;
  boolean polaroidMode;
  public int imagePaddingBottom;
  public int imageFrameWidth;
  public int imageFrameHeight;
  public int imagePaddingSlide;
  public int imageWidthBy3;
  public int imageWidthDoubleBy3;
  // from getFolderIcons()
  public int origThumbWidth;
  public int origThumbHeight;
  // from thumbScaleInit();
  int folderThumbScale;
  public int origOrigThumbWidth;
  public int origOrigThumbHeight;
  public int miniThumbContainer;
  // from thumbScaleInit();
  int folderThumbWidth;
  int folderThumbHeight;
  public int folderNewWidth;
  public int folderNewHeight;
  public int folderNewVPad;
  public int folderNewHPad;

  // Other skin variable declarations here

  public Utils(AlbumBean engine) {
    super(engine);
    Map skinVars = engine.getSkinVariables();
    // from makeThumbLinks();
    numberOfMiniThumbs = ((Integer)skinVars.get("numberOfMiniThumbs")).intValue();
    sameSizeFilterIndex = ((Boolean)skinVars.get("sameSizeFilterIndex")).booleanValue();
    miniThumbAdjust = ((Integer)skinVars.get("miniThumbAdjust")).intValue();
    // from makeNavElement();
    slideShowContinuous = ((Boolean)skinVars.get("slideShowContinuous")).booleanValue();
    // from imageCalc ();
    imagePaddingAdjust = ((Integer)skinVars.get("imagePaddingAdjust")).intValue();
    polaroidMode = ((Boolean)skinVars.get("polaroidMode")).booleanValue();
    // from thumbScaleInit();
    folderThumbScale = ((Integer)skinVars.get("folderThumbScale")).intValue();
    // Other skin variables gets defined here

  }

  // Generate drop box options for quick navigation
  public void addLinks() {
    if (totalIndexes == 0) totalIndexes = 1;
    for (int i=1; i<=totalIndexes; i++) {
      out.print("<option");
      if (i == indexNum) out.print(" selected=\"selected\"");
      out.println(" value=\"" + engine.getIndexPageName() + (i == 1 ? "" : ""+i) + engine.getPageExtension() + "\">" +    "$text.page " + i + "</option>");
    }
  }

String makeThumbLinks() {
 	// This routine loads all of the HTML code required for the row of minithumnbs into a single variable for use by the skin

        // Public variables required outside this method: None

	// Start of non-UI variables required to be read from beanshell
	portraitMode = ((Boolean)get("portraitMode")).booleanValue();
        thumbStyle = ((String)get("thumbStyle"));
	// End of non-UI variables required to be read from beanshell
		int nthumbs = 0; //init
		int nThumbs = numberOfMiniThumbs; // Default
		if (nthumbs != 0) nThumbs = nthumbs;
		int curr = imageNum-1;
		int start = 0;
		if (nThumbs < totalImages) {
			start = curr-nThumbs/2;
			if (start < 0) start = 0;
			else if (start+nThumbs >= totalImages) start = totalImages-nThumbs;
		}

		StringBuffer buf = new StringBuffer();
		thumbStyle = ( (portraitMode) ? " style=\"display: block\u003b padding-bottom: 2px\u003b \"" : "" );
		for (int i=start; (i<start+nThumbs) && (i<totalImages); i++) {
			Map vars = (Map)fileVariables.get(files[i]);

			if ( sameSizeFilterIndex ) {
				buf.append("<a href=\"" + vars.get("currentPage") + "\">" + "<img src=\"" + vars.get("thumbPath") + "\"" + " class=\"minithumb" + ((i == curr)? "Current" : "") + "\"" + " width=\"" +  (int)(((Integer)vars.get("maxThumbWidth")).intValue()*((float)miniThumbAdjust/100)) + "\" height=\"" + (int)(((Integer)vars.get("maxThumbHeight")).intValue()*((float)miniThumbAdjust/100)) + "\"" + " alt=\"" + vars.get("label") + "\"" + thumbStyle + " title=\"" + vars.get("label") + "\" ></a>\n");
                        } else {
				buf.append("<a href=\"" + vars.get("currentPage") + "\">" + "<img src=\"" + vars.get("thumbPath") + "\"" + " class=\"minithumb" + ((i == curr)? "Current" : "") + "\"" + ( portraitMode ? "" : "") + " width=\"" +  (int)(((Integer)vars.get("thumbWidth")).intValue()*((float)miniThumbAdjust/100)) + "\" height=\"" + (int)(((Integer)vars.get("thumbHeight")).intValue()*((float)miniThumbAdjust/100)) + "\"" + " alt=\"" + vars.get("label") + "\"" + thumbStyle + " title=\"" + vars.get("label") + "\" ></a>\n");
                        }
 		}
		return buf.toString();
}

String makeNavElement() {
  // This routine loads all of the HTML code required for the navigation buttons into a single variable for use by the skin

  // Public variables required outside this method: None

  // Start of non-UI variables required to be read from beanshell
  portraitModeLinefeed = ((String)get("portraitModeLinefeed"));
  buttonSetPath = ((String)get("buttonSetPath"));
  firstPage = ((String)get("firstPage"));
  lastPage = ((String)get("lastPage"));
  indexPage = ((String)get("indexPage"));
  // End of non-UI variables required to be read from beanshell

  StringBuffer buf = new StringBuffer();

  buf.append("<!-- First button -->\n");
  if (previousPage != null) {
    buf.append("<a href=\"" + firstPage + "\"><img src=\"" + buttonSetPath + "/first.gif\" alt=\"" + texts.getString("firstPage") + "\" title=\"" + texts.getString("firstPage") + "\" ></a>" + portraitModeLinefeed + "\n");
  } else {
    buf.append("<img src=\"" + buttonSetPath + "/first_disabled.gif\" alt=\"" + texts.getString("atFirstPage") + "\" title=\"" + texts.getString("atFirstPage") + "\" >" + portraitModeLinefeed + "\n");
  }

  buf.append("<!-- Previous button -->\n");
  if (previousPage != null) {
    buf.append("<a href=\"" + previousPage + "\"><img src=\"" + buttonSetPath + "/previous.gif\" alt=\"" + texts.getString("previousPage") + "\" title=\"" + texts.getString("previousPage") + "\" ></a>" + portraitModeLinefeed + "\n");
  } else {
    buf.append("<img src=\"" + buttonSetPath + "/previous_disabled.gif\" alt=\"" + texts.getString("atFirstPage") + "\" title=\"" + texts.getString("atFirstPage") + "\" >" + portraitModeLinefeed + "\n");
  }

  buf.append("<!-- Index button -->\n");
  buf.append("<a href=\"../" + indexPage + "\"><img src=\"" + buttonSetPath + "/index.gif\" alt=\"" + texts.getString("indexPage") + "\" title=\"" + texts.getString("indexPage") + "\" ></a>" + portraitModeLinefeed + "\n");

  buf.append("<!-- Next button -->\n");
  if (nextPage != null) {
    buf.append("<a href=\"" + nextPage + "\"><img src=\"" + buttonSetPath + "/next.gif\" alt=\"" + texts.getString("nextPage") + "\" title=\"" + texts.getString("nextPage") + "\" ></a>" + portraitModeLinefeed + "\n");
  } else {
    buf.append("<img src=\"" + buttonSetPath + "/next_disabled.gif\" alt=\"" + texts.getString("atLastPage") + "\" title=\"" + texts.getString("atLastPage") + "\" >" + portraitModeLinefeed + "\n");
  }

  buf.append("<!-- Last button -->\n");
  if (nextPage != null) {
    buf.append("<a href=\"" + lastPage + "\"><img src=\"" + buttonSetPath + "/last.gif\" alt=\"" + texts.getString("lastPage") + "\" title=\"" + texts.getString("lastPage") + "\" ></a>" + portraitModeLinefeed + "\n");
  } else {
    buf.append("<img src=\"" + buttonSetPath + "/last_disabled.gif\" alt=\"" + texts.getString("atLastPage") + "\" title=\"" + texts.getString("atLastPage") + "\" >" + portraitModeLinefeed + "\n");
  }

  buf.append("<!-- Slide show button -->\n");

  if ((imageNum != totalImages) || slideShowContinuous) {
	buf.append("<script type=\"text/javascript\">\n");
	buf.append("<!--\n");
	buf.append("if (readCookie('slideShow') == 'true') {\n");

	buf.append("	document.write(\"	<a onclick=\\\"stopSlideShow(); document.location.reload(false); return false;\\\" href=\\\"#\\\"><img src=\\\"" + buttonSetPath + "/slideshowstop.gif\\\" alt=\\\"" + texts.getString("stopSlideShow") + "\\\" title=\\\"" + texts.getString("stopSlideShow") + "\\\" ><\\/" + "a>\");\n");

	buf.append("} else {\n");

	buf.append("	document.write(\"	<a onclick=\\\"setSlideShowCookie();\\\" href=\\\"" + ( (imageNum == totalImages ) ? firstPage : nextPage) + "\\\"><img src=\\\"" + buttonSetPath + "/slideshowstart.gif\\\" alt=\\\"" + texts.getString("startSlideShow") + "\\\" title=\\\"" + texts.getString("startSlideShow") + "\\\"><\\/" + "a>\");\n");

	buf.append("}\n");
	buf.append("-->\n");
	buf.append("</script>\n");
	buf.append(portraitModeLinefeed + "\n");
  }

  return buf.toString();

}

public void imageCalc() {
	// This routine calculates values to be used later for the padding around the image.It allows for dynamic image sizes, and adjusts the and dimensions automatically

  	// Public variables required outside this method: imagePaddingBottom, imageFrameWidth, imageFrameHeight, imagePaddingSlide, imageWidthBy3, imageWidthDoubleBy3

  	// Start of non-UI variables required to be read from beanshell
	  double polaroidStretchFactor = ((Double)get("polaroidStretchFactor")).doubleValue();
 	// End of non-UI variables required to be read from beanshell

	double imageDiagonal = Math.sqrt(imageWidth * imageWidth + imageHeight * imageHeight); // Calculate the hypotenuse of the image, this is used for further calculations
	imagePaddingSlide = (int)((imageDiagonal / 33)*((float)imagePaddingAdjust/100));        // How much padding will we need around the image? It changes according to the size of the image and can also be adjusted via user variable
	if (polaroidMode) {
		imagePaddingBottom = (int)(imagePaddingSlide * polaroidStretchFactor); 	// We stretch out the bottom to make the polaroid effect (if selected)
	} else {
		imagePaddingBottom = imagePaddingSlide; 				// Because Polaroid mode is not used, all the padding around the edges will be equal
	}
	imageFrameWidth = imageWidth + (2 * imagePaddingSlide) -1;   // We need to setup the background image for the right size under the padded edges
	imageFrameHeight = imageHeight + (imagePaddingSlide + imagePaddingBottom) -1;	// We need to setup the background image for the right size under the padded edges
	imageWidthBy3 = imageWidth/3; // Used later in the image map - done for purposes of optimisation
	imageWidthDoubleBy3 = 2*imageWidth/3; // Used later in the image map - done for purposes of optimisation
}

public void getFolderIcons() throws java.io.IOException {
  // Try to replace folder icons with prepresentative image from subdirectory

  // Public variables required outside this method: origThumbWidth, origThumbHeight, folderNewHPad, folderNewVPad

  // Start of non-UI variables required to be read from beanshell
  // End of non-UI variables required to be read from beanshell

    if (currentFile.isDirectory()) {
    File subDir = currentFile;
    File subDir2 = subDir;
    File iconFile = null;
    String folderIconDirectory = null;

    // If meta.properties exists and points to an icon file, use it
    File propsFile = new File(subDir, "meta.properties");
    if (propsFile.exists()) {
      Map props = IO.readMapFile(propsFile);
	folderIconDirectory = (String)props.get("folderIconDirectory");
      if(folderIconDirectory != null && folderIconDirectory.length() > 0) {
	  subDir = new File(subDir, "/" + folderIconDirectory);
      }
      if (!subDir.exists()) subDir = subDir2;

	String folderIcon = (String)props.get("folderIcon");
      if(folderIcon != null && folderIcon.length() > 0) {
        iconFile = new File ( subDir , folderIcon) ;
        if (!iconFile.exists()) iconFile = null;
      }
    }
    if((iconFile == null) && (engine.isUseThumbForFolderIcon())) {
      // Try to use the first image as folder icon
    File[] list = subDir.listFiles();
      for (int i=0; i<list.length; i++) {
        if (FileFilters.isFileSupported(list[i])) {
          iconFile = list[i];
          break;
       }
      }
    }
    if (iconFile != null) {
      // Process this image so we can extract width and height
	// Note for this skin we do not actually use the adjusted width and height, we allow the browser to shrink the thumb to the size of the folder.gif icon.
      engine.registerVariables(iconFile, outputDirectory);  // Private = might change
      Map vars = (Map)fileVariables.get(iconFile);
      // Redefine variables
      iconPath = encode( ( (subDir == subDir2) ? subDir.getName() : subDir2.getName() + "/" + folderIconDirectory) + "/thumbs/" + engine.jpegName(iconFile.getName()));
      if (!iconFile.isDirectory()) thumbPath = iconPath;
      thumbWidth = ((Integer)vars.get("thumbWidth")).intValue();
      thumbHeight = ((Integer)vars.get("thumbHeight")).intValue();
      folderNewHPad = folderNewWidth; // Since this isn't a folder.gif case reset the previously calculated offset for overlay over a thumbnail.
    } else {
	// Maybe we have scaled our folder thumbnails, but we don't want to scale the folder.gif itself, now we scale folder.gif back to original size, but only if we have scaled up, not down.
      if (folderThumbScale > 100) {
        origThumbWidth = origOrigThumbWidth;
        origThumbHeight = origOrigThumbHeight;
        folderNewVPad = 0; // Since we are dealing with a folder.gif, reset the offset for the foldernew.gif icon
      }
    }
  }
}

public void thumbScaleInit() {
 // Normally, any thumbnails representing folders will be the same size as folder.gif, but here we can scale them if desired, but backup the value first
  // Start of non-UI variables required to be read from beanshell
  folderThumbWidth = ((Integer)get("folderThumbWidth")).intValue();
  folderThumbHeight = ((Integer)get("folderThumbHeight")).intValue();
  folderNewWidth = ((Integer)get("folderNewWidth")).intValue();
  folderNewHeight = ((Integer)get("folderNewHeight")).intValue();
  folderNewHPad = folderNewWidth; folderNewVPad = 0; // Init these two variables because old values were being left over from previous folder...
  // End of non-UI variables required to be read from beanshell

  thumbWidth = folderThumbWidth; // from folder.gif (via init.bsh)
  thumbHeight = folderThumbHeight;
  origOrigThumbWidth = thumbWidth;
  origOrigThumbHeight = thumbHeight;
  origThumbWidth = (int)(thumbWidth * ((float)folderThumbScale/100));
  origThumbHeight = (int)(thumbHeight * ((float)folderThumbScale/100));
  miniThumbContainer = (int)(((float)folderThumbScale/100)*origOrigThumbWidth*1.4);
  if (folderThumbScale < 100) {
	  folderNewWidth = (int)(folderNewWidth * ((float)folderThumbScale/100)); // If thumbnail is scaled down, we need to also shrink the new icon a little.
	  folderNewHeight = (int)(folderNewHeight * ((float)folderThumbScale/100));
	  folderNewHPad = folderNewWidth;
  }
  if (folderThumbScale > 100) {
	  folderNewVPad = (int)(((folderNewHeight * ((float)folderThumbScale/100)) - folderNewHeight)*0.85); // When a thumbnail is scaled larger we need to push the "new" icon a little lower
	  folderNewHPad = (int)(((miniThumbContainer-folderThumbWidth)/2)-10) + folderNewWidth; // For folder.gif cases, shift new icon further to the left to line up over the icon
  }
}

private String encode(String s) {
      // Performs encoding similar to classic URL encoding but also
      // encodes accented characters and encodes space to %20 (Netscape in mac likes this)
      // Seems to be neccesary for the part of an URL that is before the ?

      if (engine.isUrlEncode()) {
		return IO.urlEncode(s);
   	} else {
		return s;
      }
   }

}