# Picasa album helper, by Hackerdude.
# For usage, see http://www.hackerdude.com/2006/02/27/parse-picasa-xml-with-rails/
#
# Distributed under the creative commons Attribution license.
# http://creativecommons.org/licenses/by/2.0/
# 
# This basically means, do whatever you want with it, give me credit for this piece
# of it.
# 
# If you do end up using it, I'd appreciate a line. Please email david at hackerdude
module PicasaAlbumHelper

  require 'net/http'
  require 'uri'
  require 'rexml/document'


  # Encapsulates the picasa album. Follows the same attribute
  # names as the XML payload
  class PicasaAlbum
    attr_accessor :firstImage, :lastImage
    attr_reader :albumCaption, :albumItemCount, :albumName
    
    attr_reader :entries
    attr_reader :item_keys, :album_keys
    attr_accessor :hash

    # A hash of entries keyed by their thumbnail name
    attr_reader :thumbnails

    def initialize
        @hash = Hash.new
        @item_keys = ["itemName", "itemLargeImage", "itemCaption", 
            "itemThumbnailWidth", "itemThumbnailHeight", "itemThumbnailImage",
            "prevThumbnail", "nextThumbnail",
            "nextTarget", "prevTarget", "itemWidth", "itemHeight",
            "firstTarget", "lastTarget", "nextImage", "prevImage"]
        @album_keys = ["albumName", "albumCaption", "albumItemCount"]
    end

    def albumName=(name)
        @albumName = name
        @hash['albumName'] = name unless name.nil?
    end
    def albumCaption=(caption)
        @albumCaption = caption
        @hash['albumCaption'] = caption unless caption.nil?
    end
    def albumItemCount=(count)
        @albumItemCount = count
        @hash['albumItemCount'] = count
    end

    def entries=(entries)
      @entries = entries
      # Set the thumbnails
#      @thumbnails = {}
      prev = @entries.last.itemThumbnailImage
      @entries.each {|entry| 
#        @thumbnails[entry.itemThumbnailImage] = entry
        entry.prevThumbnail = prev
        prev = entry.itemThumbnailImage
      }
      nxt = @entries.first.itemThumbnailImage
      @entries.reverse_each {|entry| 
        entry.nextThumbnail = nxt
        nxt = entry.itemThumbnailImage
      }
    end

    # Creates the album out of a URL
    def self.create_album   #(base_url, index_path)
      result = PicasaAlbum.new()
      xml_string = File.new("index.xml")
      xml_doc = REXML::Document.new(xml_string)
      xml_string.close
      root_node = xml_doc.root
      result.albumName = root_node.elements["albumName"].text.strip
      result.albumCaption = root_node.elements["albumCaption"].text.strip
      result.albumItemCount = root_node.elements["albumItemCount"].text.strip
      puts "Found #{result.albumItemCount} images. Loading xml..."
      entries = []
      target = 1
      nextTarget = 2
      prevTarget = result.albumItemCount
      images_node = root_node.elements["images"]
      images_node.each_element('image') { |imageElement| 

        fileEntry = PicasaFileEntry.new(imageElement)
        fileEntry.target = target
        fileEntry.prevTarget = prevTarget
        if ( nextTarget == result.albumItemCount.to_i+1) then
            fileEntry.nextTarget = 1
        else
            fileEntry.nextTarget = nextTarget
        end
        fileEntry.firstTarget = 1
        fileEntry.lastTarget = result.albumItemCount
        result.firstImage = imageElement.elements["firstImage"].text.strip
        result.lastImage = imageElement.elements["lastImage"].text.strip


        entries.push(fileEntry)
        prevTarget = target
        nextTarget += 1
        target += 1

      }
      result.entries = entries;
        puts "Done."
      return result
    end

  end


  # Encapsulates a single file entry. Follows the same attribute
  # names as the XML payload.
  class PicasaFileEntry
    include Comparable

    # Some simple metadata
    attr_accessor :isFirstImage, :isLastImage, :isPrevImage, :isNextImage,
      :itemLargeImage

    # The meat of this entry
    attr_accessor :itemName,
      :itemThumbnailImage, :itemThumbnailWidth, :itemThumbnailHeight,
      :itemCaption, :hash

    attr_accessor :nextImage, :prevImage

    attr_reader :target, :nextTarget, :prevTarget, :firstTarget, :lastTarget
    attr_reader :itemWidth, :itemHeight
    attr_reader :nextThumbnail, :prevThumbnail

    def target=(target)
        @target = target
        @hash['target'] = "target#{target.to_s}.html"
    end
    def nextTarget=(target)
        @nextTarget = target
        @hash['nextTarget'] = "target#{target.to_s}.html"
    end
    def prevTarget=(target)
        @prevTarget = target
        @hash['prevTarget'] = "target#{target.to_s}.html"
    end
    def firstTarget=(target)
        @firstTarget = target
        @hash['firstTarget'] = "target#{target.to_s}.html"
    end
    def lastTarget=(target)
        @lastTarget = target
        @hash['lastTarget'] = "target#{target.to_s}.html"
    end
    def itemWidth=(width)
        @itemWidth = width
        @hash['itemWidth'] = width.to_s
    end
    def itemHeight=(height)
        @itemHeight = height
        @hash['itemHeight'] = height.to_s
    end
    def prevThumbnail=(image)
        @prevThumbnail = image
        @hash['prevThumbnail'] = @prevThumbnail
    end
    def nextThumbnail=(image)
        @nextThumbnail = image
        @hash['nextThumbnail'] = @nextThumbnail
    end

    # The constructor needs an XML element to read the information from.
    def initialize(node)
        @hash = {}

        @itemWidth = node.elements["itemWidth"].text.strip
        @itemHeight = node.elements["itemHeight"].text.strip
        @itemName   = node.elements["itemName"].text.strip
        @hash['itemName'] = @itemName
        @itemCaption = node.elements["itemCaption"].text.strip
        @hash['itemCaption'] = @itemCaption
        @itemLargeImage = node.elements["itemLargeImage"].text.strip
        @hash['itemLargeImage'] = @itemLargeImage
        @itemThumbnailImage = node.elements["itemThumbnailImage"].text.strip
        @hash['itemThumbnailImage'] = @itemThumbnailImage
        @itemThumbnailWidth = node.elements["itemThumbnailWidth"].text.strip
        @hash['itemThumbnailWidth'] = @itemThumbnailWidth
        @itemThumbnailHeight = node.elements["itemThumbnailHeight"].text.strip
        @hash['itemThumbnailHeight'] = @itemThumbnailHeight

        @target = 0
        puts node.elements['nextImage'].text if defined? debug
        unless node.elements['nextImage'].text.nil? then
            @nextImage = node.elements["nextImage"].text.strip 
            @hash['nextImage'] = @nextImage
        end
        unless node.elements['prevImage'].text.nil? then
            @prevImage = node.elements["prevImage"].text.strip 
            @hash['prevImage'] = @prevImage
        end

    end
      
    def <=>(other)
        self.target <=> other.target
    end
  end

  # Creates a slideshow using a picasa index.xml file.
  # 
  # == Usage: 
  # include lightbox.js in your page
  # 
  #   slideshow( "http://localhost:3000/", "images/travel/album1/index.xml", 
  #              { :max_per_row=3, :max_rows=4 } )
  def slideshow( base_url, index_file, options = {} )
#    max_rows = options[:max_rows]
#    max_rows = 9999 unless max_rows != nil
#    max_per_row = options[:max_per_row]
#    max_per_row = 10 unless max_per_row != nil

#    fullURL = "#{base_url}#{index_file}"
#    # Get the base path for the picasa album
#    itemPath = /http:\/\/([^\/]*)\/(.*)\/([A-Za-z0-9.]*)/.match(fullURL)[2]

    # Get album info from picasa
    album = PicasaAlbum.create_album    #(base_url, index_file)
    album_thumbnails = album.thumbnails
    html_output=""

#    # Now let's render those images.. 
#    row = 0
#    column = 0

    album_thumbnails.keys.each { |itemThumbnailImage| 
#      column += 1
#      if column > max_per_row then
#        html_output += "<br/>"
#        column = 0
#        row+= 1
#      end
      item = album_thumbnails[itemThumbnailImage]
      itemLargeImage = item.itemLargeImage
      itemCaption = item.itemCaption

      itemThumbnailImage = '' if itemThumbnailImage == nil
      itemCaption = '' if itemCaption == nil
      itemLargeImage = '' if itemLargeImage == nil

      html_output += "<a href=\"#{itemPath}/#{itemLargeImage}\" "
      html_output += "rel=\"lightbox\" "
      html_output += "title=\"#{itemCaption}\">"
      html_output += "<img src=\"#{itemPath}/#{itemThumbnailImage}\"></a> "
    }
    return html_output

  end

end

