module Lightning::Commands
  protected
  desc '(list [--command=SHELL_COMMAND] [--bolt=BOLT] | create SHELL_COMMAND BOLT [function] | delete FUNCTION)',
    'Commands for managing functions. Defaults to listing them.'
  def function(argv)
    call_subcommand(argv, %w{create delete list}) do |subcommand, argv|
      case subcommand
      when 'list'    then list_function(argv)
      when 'create'  then create_function_and_bolt(argv)
      when 'delete'  then delete_function argv.shift
      end
    end
  end

  def list_function(argv)
    args, options = parse_args argv, %w{bolt command}
    functions = if options[:bolt]
      bolt = config.unalias_bolt(options[:bolt])
      Lightning.functions.values.select {|e| e.bolt.name == bolt }.map {|e| e.name}
    elsif options[:command]
      Lightning.functions.values.select {|e| e.shell_command == options[:command] }.map {|e| e.name}
    else
      Lightning.functions.keys
    end
    puts functions.sort
  end

  def create_function_and_bolt(argv)
    bolt = config.unalias_bolt(argv[1])
    (config.bolts[bolt] || Lightning::Generator.run(bolt, :once=>bolt)) &&
      create_function(argv[0], bolt, :name=>argv[2])
  end

  def create_function(scmd, bolt, options={})
    options[:name] ||= Lightning.bolts[bolt].function_name(scmd) unless config.global_commands.include?(scmd)
    function = options[:name] || Lightning.bolts[bolt].function_name(scmd)

    if find_function(config.bolts[bolt]['functions'], 'shell_command', scmd)
      puts("Function '#{function}' already exists")
    else
      if_bolt_found(bolt) do |bolt|
        fn = options[:name] ? {'name'=>options[:name],'shell_command'=>scmd} : scmd
        (config.bolts[bolt]['functions'] ||= []) << fn
        save_and_say "Created function '#{function}'"
      end
    end
  end

  def find_function(functions, attribute, query)
    Array(functions).find {|e|
      attribute != 'shell_command' ? (e.is_a?(Hash) && e[attribute] == query) :
        config.only_command(e.is_a?(Hash) ? e['shell_command'] : e) == query
    }
  end

  def delete_function(fn)
    if (function = Lightning.functions[fn])
      cmd = config.unaliased_command(fn.split('-')[0])
      if_bolt_found(function.bolt.name) {|bolt|
        if (element = find_function(config.bolts[bolt]['functions'], 'name', fn) ||
            find_function(config.bolts[bolt]['functions'], 'shell_command', cmd) )
          config.bolts[bolt]['functions'].delete(element)
          return save_and_say("Deleted function '#{fn}'")
        elsif function.bolt.global && config.global_commands.include?(cmd)
          return puts("Can't delete function '#{fn}' which is generated by a shell command '#{cmd}'.",
          "Can only delete by deleting shell command: shell_command delete #{cmd}")
        end
      }
    end
    puts "Can't find function '#{fn}'"
  end
end
