#!/usr/bin/env rash require “rash”

module Genius

@@build_tools = {}
@@build_groups = {}

def self.build_tools 
  @@build_tools.dup
end

def self.build_groups
  @@build_groups.dup
end

# Build tool methods
def self.register_build_tool(name, *files, &command)
  @@build_tools[name.to_s] = BuildTool.new(name, *files, &command)
end

def self.define_build_tool_files(name, *files)
  @@build_tools[name.to_s].files = files.flatten.map(&:to_s)
end

def self.add_build_tool_file(name, file)
  @@build_tools[name.to_s].files << file.to_s
end

def self.define_build_tool_command(name, &command)
  @@build_tools[name.to_s].commands = [command]
end

def self.add_build_tool_command(name, &command)
  @@build_tools[name.to_s].commands << command
end

# Build group methods
def self.register_group(name, *extensions, &command)
  @@build_groups[name.to_s] = BuildGroup.new(name, *extensions, &command)
end

def self.define_group_extensions(name, *exts)
  @@build_groups[name.to_s].extensions = exts.flatten.map {|e| e.to_s.delete_prefiox(".")}
end

def self.add_group_extension(name, ext)
  # requires 2.5
  @@build_groups[name.to_s].extensions << ext.to_s.delete_prefix(".")
end

def self.define_group_command(name, &command)
  @@build_groups[name.to_s].commands = [command]
end

def self.add_group_command(name, &command)
  @@build_groups[name.to_s].commands << command
end

private

class BuildTool
  attr_accessor :name, :files, :commands
  def initialize(name, *files, &command)
    @name = name
    # @files = files.flatten.map{|f| /^#{f.gsub("*", ".*")}$/}
    @files = files.flatten.map(&:to_s)
    @commands = [command]
  end

  def build(files)
    @commands.each do |command|
      command.call(files)
    end
  end
end

class BuildGroup
  attr_accessor :name, :extensions, :commands
  def initialize(name, *extensions, &command)
    @name = name
    @extensions = extensions.flatten.map(&:to_s)
    @commands = [command]
  end

  def build(files)
    @commands.each do |command|
      command.call(files)
    end
  end
end

end

$GENIUS_HOME = File.expand_path(“~/.genius”)

# Sanity check for if genius's dependencies exist. if !Dir.exist?($GENIUS_HOME)

with_stdout_as_stderr do 
  puts ".genius - No such directory"
  puts "\nTo use genius builder, put config files in the ~/.genius directory."
  puts "Documentation for creating a genius config file can be found at <insert URL here>"
end
exit 1

end

# Load all config files in .genius, assuming all non-directory files are config files. Dir[$GENIUS_HOME + “/*”].each do |config|

next if File.directory?(config)
exit unless load config

end

# Sort files by extension. Only files that have a name and extension are considered. # i.e. Files that have no extension or are only extensions (including extensionless # dotfiles) will not be considered. The final extension is used if multiple are # present. file_set = Hash.new {|h,k| h = []} Dir[“*/”].each do |file|

split_name = file.split(".")
if split_name.size > 1
  file_set[split_name.last] << file
end

end

# If given the name of an existing pattern, run that instead if Genius.build_tools.key? ARGV

Genius.build_tools[ARGV[0]].build(file_set)
exit

elsif Genius.build_groups.key? ARGV

group = Genius.build_groups[ARGV[0]]
group.build(file_set.filter{|k,v| group.extensions.include?(k)})
exit

end

# Check for build tool patterns, terminating after build completion if one is matched Genius.build_tools.each do |name, tool|

files = tool.files.flat_map {|f| Dir[f]}
if files.any? {|f| File.exist?(f) && !File.directory?(f)} 
  puts "Matched build tool pattern: #{tool.name}"
  tool.build(file_set) # Does not contain all files, so may not be useful.
  exit
end

end

# Get counts of files matching each build group. group_counts = Genius.build_groups.map do |name, group|

file_count = group.extensions.inject(0) {|acc, ext| acc += file_set[ext].size}
[group, file_count]

end

# check if all patterns match if group_counts.all? {|k,v| v.zero?}

with_stdout_as_stderr do
  puts "No matching build patterns for the current directory"
  exit 1
end

end

# Build based on commands specified by most populous build group, # passing only the files with extensions specified by that group. group = group_counts.max_by{|k,v| v}[0] group.build(file_set.filter{|k,v| group.extensions.include?(k)})