#!/usr/bin/env ruby
# Frozen_String_Literal: true
# Written by Sourav Goswami <souravgoswami@protonmail.com>

BASE = File.join(__dir__, 'oreo_base_cursors')

# Configuration file to read
CONFIG_FILE = 'colours.conf'

# Output directory
OUT_DIR = File.join(File.expand_path('..', __dir__), 'src')

# Content of index.theme inside each theme
INDEX_THEME = proc do |x|
	<<~EOF
		[Icon Theme]
		Name=Oreo #{x.split(?_).map(&:capitalize).join(?\s)} Cursors
		Comment=design by varlesh | colour by #{Process.argv0}
	EOF
end

### Code ###
puts "Error with the output directory. Does it exist? Is it writable?" unless File.writable?(OUT_DIR)

colours = {}

def colour_validation!(colour, i, silent = false)
		# Colours are uppercased
		colour.upcase!

		# Spaces are trimmed
		colour.strip!

		# Make sure all the colour characters are valid hex
		if !!colour[/[^a-fA-F0-9#]/] || ![3, 6].include?(colour.start_with?(?#) ? colour[1..-1].length : colour.length)
			puts %Q(:: Line #{i.next}: "#{colour}" is not a valid colour) unless silent
			return false
		end

		# Make sure colour starts with #
		colour.prepend(?#) unless colour.start_with?(?#)

		# Make sure colour is 6 characters long
		colour.replace(?# + colour.chars[1..-1].map { |y| y + y }.join) if colour.length == 4
		true
end

if File.readable?(CONFIG_FILE)
	IO.readlines(CONFIG_FILE).each_with_index do |x, i|
		next if x.start_with?(?#) || x.strip.empty?

		# Label colour
		label = +'#fff'
		l = +x.split[3].to_s
		label = l if colour_validation!(l, i, true)
		colour_validation!(label, 0)

		# Shadow colour
		shadow = +'#000'
		s = +x.split[4].to_s
		shadow = s if colour_validation!(s, i, true)
		colour_validation!(shadow, 0)

		# Shadow opacity
		shadow_opacity = '0.3'
		so = x.split.map(&:strip).select { |y| y.to_f.to_s == y || y.to_i.to_s == y }[-1]
		shadow_opacity = +so.strip if so

		# Get cursor name and colour
		name, colour = x.split(?=).then { |y| [+y[0].to_s.strip, +y[1].to_s.split[0].to_s.strip] }

		# Make sure colour name is not 0 characters long or too long
		if name.length.zero? || name.length > 512
			puts %Q(:: Line #{i.next}: "#{name}" is not a valid name.)
			next
		end

		next unless colour_validation!(colour, i)

		# Print RGB in the terminal
		r, g, b = colour[1..2].to_i(16), colour[3..4].to_i(16), colour[5..6].to_i(16)
		lr, lg, lb = label[1..2].to_i(16), label[3..4].to_i(16), label[5..6].to_i(16)
		sr, sg, sb = shadow[1..2].to_i(16), shadow[3..4].to_i(16), shadow[5..6].to_i(16)

		puts "\e[1;38;2;#{r};#{g};#{b}m:: #{name}:"\
			"\e[0m \e[38;2;#{r};#{g};#{b}m#{colour}"\
			"\e[0m | \e[38;2;#{lr};#{lg};#{lb}mLabel"\
			"\e[0m | \e[38;2;#{sr};#{sg};#{sb}mShadow(#{shadow_opacity})"\
			"\e[0m |"

		colours.merge!(name => [colour, label, shadow, shadow_opacity])
	end
else
	puts ":: Unable to read #{CONFIG_FILE}"
end

colours.each do |x, y|
	dirname = File.join(OUT_DIR, "oreo_#{x}_cursors")
	Dir.mkdir(dirname) unless Dir.exist?(dirname)

	# Delete files from dirname if it's not empty. The reason is to get rid of excess files.
	Dir.children(dirname).each do |x|
		file = File.join(dirname, x)
		File.delete(file)
	end

	Dir.glob("#{BASE}/*svg.oreo").each do |z|
		if File.file?(z)
			dest_file = File.join(dirname, File.basename(z).split(?.).tap(&:pop).join(?.))
			data = IO.read(z)

			# Background Colour
			data.gsub!(/\{\{ background \}\}/i, y[0])

			# Label Colour
			data.gsub!(/\{\{ label \}\}/i, y[1])

			# Shadow Colour
			data.gsub!(/\{\{ shadow \}\}/i, y[2])

			# Shadow Opacity
			data.gsub!(/\{\{ shadow\s*opacity \}\}/i, y[3])

			IO.write(dest_file, data)
		end
	end

	# Write to index file
	IO.write(File.join(dirname, 'index.theme'), INDEX_THEME.call(x))
end
