module Idonethis::UseCases
  class Cli
    class << self
      def apply(argv={}, adapters={})
        args = parse(argv)
      
        command,*rest = argv

        command = "help" unless command

        log      = args[:verbose] == true ? adapters[:log] : ->(_){} 
        internet = adapters[:internet]
        views    = adapters[:views]    || fail("You need to supply the :views adapter")
        settings = adapters[:settings] || fail("You need to supply the :settings adapters")
        
        args.merge!({ opts: rest, log: log, internet: internet, view: views[:list]})

        log.call "args: #{args}, command: #{command}, rest: #{rest}"
        
        use_case = choose command.to_sym, adapters, views, rest 

        unless use_case
          log.call "No command <#{command.to_sym}> found"
          return
        end

        use_case.call settings.credential, args
      end
      
      private 
      
      def choose(command, adapters, views, opts)
       use_cases = {
          list:   Idonethis::UseCases::List.method(:apply),
          new:    Idonethis::UseCases::New.method(:apply),
          config: Idonethis::UseCases::Config.method(:apply),
          git:    ->(_, args) { Idonethis::UseCases::Git.apply(_, args.merge(git: adapters[:git], view: ->(msg) { puts msg }, fs: adapters[:fs]))},
          help:   ->(credential, args) { puts "TODO: implement help" }
        }
        
        if command == :list && opts.include?("teams")
          return ->(credential, args) { 
            Idonethis::UseCases::Teams.apply(credential, args.merge(view: views[:teams]))
          }          
        end
        
        use_case = use_cases[command]
      end
      
      def choose_log(args={})
        args[:verbose] == true ? ->(msg){puts "[LOG] #{msg}"} : ->(_){}
      end 
      
      def parse(argv={})
        args = {}

        require 'optparse'
        
        OptionParser.new do |opts|
          opts.banner = "Usage: command [options]"

          opts.on("-v", "--verbose", "Run verbosely") do |v|
            args[:verbose] = v
          end

          opts.on("-m MESSAGE", "Message") do |m|
            args[:message] = m
          end

          opts.on("-d", "Dry run") do |_|
            args[:dry_run] = true
          end
          
          opts.on("-t TEAM", "--team TEAM" "Run against this team") do |team_name|
            args[:team] = team_name
          end

          opts.on("-s WHEN", "--since WHEN" "Show git commits since when") do |value|
            args[:since] = value
          end
        end.parse!
        
        args
      end
    end
  end
end