#!/usr/bin/env ruby

require "rubygems"
require 'getoptlong'
require "zip/zip"
require "css_parser"
require "fileutils"

def open_zip(zip_file_name, nowrite=false)
	Zip::ZipFile.open(zip_file_name) do |zipfile|
		files = zipfile.select(&:file?)
		files.each do |zip_entry|
			#puts zip_entry.name
			contents = zipfile.read(zip_entry.name)
			css = ""
			if zip_entry.name.match(/\.css$/)
				# modify css here
				contents = fix_css(contents)
				# write back css file
				zipfile.get_output_stream(zip_entry.name){ |f| f.puts contents } unless nowrite
			else
				# write back non-css file
				zipfile.get_output_stream(zip_entry.name){ |f| f.puts contents } unless nowrite
			end
		end
		zipfile.commit unless nowrite
	end
end

def fix_css(contents)
	parser = CssParser::Parser.new
	parser.load_string!(contents)

	parser.each_rule_set{ |rule_set|
		rule_set.each_declaration{ |decl|
			if decl.match(/line-height/)
				rule_set.remove_declaration!(decl)
			end
		}
		if rule_set.selectors == ["body"]
			rule_set.add_declaration!("line-height", "1.2")
		elsif rule_set.selectors == ["body *"]
			rule_set.add_declaration!("line-height", "inherit")
		end
	}

	# If there is no 'body' selector, add one
	if parser.find_by_selector('body').length == 0
		css = <<-EOT.gsub(/^\t*/, '')
		body {
		  line-height: 1.2;
		}
		EOT
		parser.add_block!(css)
	end
	# If there is no 'body *' selector, add one
	if parser.find_by_selector('body *').length == 0
		css = <<-EOT.gsub(/^\t*/, '')
		body * {
		  line-height: inherit;
		}
		EOT
		parser.add_block!(css)
	end
	return parser.to_s
end

def usage
	puts <<EOT
Tool to change epub css to fix common annoyances.

Usage: #{$0.sub(/.*\//, "")} [options] <file>

-h, --help			show this message
-n				do nothing
-o <file>			output to file
EOT
	exit
end

def cmdline
	options = Hash.new
	begin
		opts = GetoptLong.new(
			[ "-h", "--help",		GetoptLong::NO_ARGUMENT ],
			[ "-n",				GetoptLong::NO_ARGUMENT ],
			[ "-o",				GetoptLong::REQUIRED_ARGUMENT ]
		)
		opts.quiet=true

		opts.each do |opt, arg|
			options[opt] = arg
		end

	rescue
		print "#{$!}\n"
		usage
	end
	if options["-h"]
		usage
	end
	return options
end

options = cmdline
infile = ARGV[0]

if options["-o"]
	FileUtils.cp(infile, options["-o"])
	infile = options["-o"]
end

open_zip(infile, options["-n"])


# the following seems to be completely evil in css:
# display: block
