
# Fails in XP packaged version of shoes with a private method access error.
# I'll wait until the XP package is updated (or not) to a more current version.

# One could change all the @console.puts (str) to @console.contents << str+'\n'
# One could get really tired to doing that a lot of times. 
class Para
  def puts(str)
	self.contents << str
	self.contents << "\n"
	# if I could force a redraw on the gui at this point that would be nice
  end
end


class SplitWXR < Shoes
  url "/", :setup

  # this is the method the Shoes.app calls (because of the url declaration)
  def setup
	@infn = "Your WXR File"
	@outfn = File.basename(@infn.delete(' '))+'-'
	@outMB = "1.75"	# its a string
	stack :margin => 10 do 
	  tagline "Split WXR Files"
	  para ["Select a Wordpress Export file and create and create a bunch of ",
		"little files that you can import. Pick your file size to match what ",
		"your host allows for PHP file_uploads."]
	  flow :margin => 10 do
		# bonus points for scanning the dir for "wordpress*.xml"
		fnbox = edit_line @infn, :width => 300 
		button "Select WXR File..." do
		  @infn = ask_open_file
		  if @infn
			fnbox.text = @infn
			@outfn = File.basename(@infn,'.*')+'-'
			@outfnbox.text = @outfn
		  end
		end
	  end
	  para ["Pick the size of each output file ",
			"or enter your own MB (the default is 1.75MB)."]
	  flow :margin => 10 do
		  # how to set the list_box's default? 
		  lb = list_box :items => ["1 MB", "2 MB", "3 MB", "4 MB",
								   "5 MB", "6 MB"] do
			@outMB = lb.text.split()[0]
			@el.text = @outMB
		  end
		  @el = edit_line @outMB, :width => 40 do
			@outMB = @el.text
		  end 
	  end
	  para "The output files will be in the same folder as the input file"
	  para ["You should enter a partial file name (without an .ext) that ",
			"I'll append \"1.wxr\" and 2.wxr and so on"]
	  @outfnbox = edit_line @outfn, :width => 300 do
		@outfn = @outfnbox.text
	  end
	  flow :margin => 30 do
		  button "Quit" do
			exit
		  end
		  para " ", :width => 200	# just make the layout pleasing. 
		  button "Make Little WXR's" do
			if !File.readable?(@infn)
			  alert("The file \"#{@infn}\" isn't readable")
			  return # exit the button block
			end
			@progressBlock.show()
			# open and parse
			inf = File.open(@infn, 'r')
			self.loadWXR(inf)		# it closes the file
			# now I write the smaller files
			chunk = 1
			chunksz = 0
			osz = ((2**20)*@outMB.to_f).to_i
			@console.puts "Chunksize = #{osz}"
			outf = nextfile(chunk)		# open the file, writes the preamble
			# start a new thread to output things and keep the GUI alive
			#th = Thread.new() do 
			  @items.each do |item|
				item.each do |ln|
				  outf.puts ln
				  chunksz += ln.length
				end
				if chunksz > osz
				  @postamble.each {|t| outf.puts t}
				  outf.close
				  chunk +=  1
				  chunksz = 0
				  outf = nextfile(chunk)
				end
			  end
			#end
			th.join
			# finish the last one
			@postamble.each {|t| outf.puts t}
			outf.close
			@console.puts "Done"
		  end
	  end
	  @progressBlock = stack :width => 1.0, :height => -50 do
		  background "#555"
		  @console = para "Progress Messages\n", :font => "Monospace 12px", :stroke => "#dfa"
		  #p @console.methods
		  # figure out para.contents
		  #p @console.contents[0].class
		  
	  end
	  @progressBlock.hide()
	  # there's show when the button is pushed. 
	end # top stack
  end # end of the setup method
  
 def loadWXR(infile)
	@preamble = []
	@postamble = []
	@items = []
	@inPre = true
	@inItems = false   
	@inPosta = false
	@curItem = []
	infile.each do |ln|
	  if @inPre
		if ln[/<item>/i]
		  @inPre = false
		  @inItems = true
		  @curItem << ln
		else
		  @preamble << ln
		end
	  elsif @inItems  == true
		if ln[/<\/channel>/]
		  @inItems = false
		  @postamble[0] = ln
		  @inPosta = true
		  next
		end
		if ln[/<\/item>/]
		  # Finalize item - move curItem to items
		  @curItem << ln
		  @items << @curItem
		elsif ln[/<item>/]
		  # start new item
		  @curItem = ln
		else
		  @curItem << ln
		end
	  elsif @inPosta == true
		@postamble << ln
	  else 
		# an error in the state machine
		$stderr.puts "Should not get here\n"
		@curItem << ln
	  end
	end
	@console.puts "#{@preamble.length} Preamble Lines"
	@console.puts "#{@items.length} Entrys"
	@console.puts "#{@postamble.length} Postamble Lines"
	infile.close()
  end # loadWXR
  
  def nextfile(ctr)
   fn = @outfn+ctr.to_s+".wxr"
   @console.puts "Writing #{fn}"
   # returns the handle
   h = File.new(fn,'w')
   @preamble.each {|ln| h.puts ln}
   return h
  end

end

# the next line fires up the GUI, calling the "/" url which maps to the setup
# method in the SplitWXR class.
Shoes.app :width => 500, :height => 640, :margin => 10 

