require 'net/scp'
require 'net/ssh'

module WhippedCream
  # Prepares a Pi for deployment, and deploys a plugin
  class Deployer
    attr_reader :plugin_filename, :pi_address

    def initialize(plugin_filename, pi_address)
      @plugin_filename = plugin_filename
      @pi_address = pi_address
    end

    def deploy
      bootstrap
      copy_plugin
      kill_all_plugins
      run_plugin
    end

    def scp
      @scp ||= Net::SCP.start(*connection_arguments)
    end

    def ssh
      @ssh ||= Net::SSH.start(*connection_arguments)
    end

    def connection_arguments
      options = { password: 'raspberry' }

      ip_address, port = pi_address.split(':')
      options.merge!(port: port) if port

      [ip_address, 'pi', options]
    end

    private

    # :nocov:  Private methods should not count against %test coverage
    def bootstrap
      ssh_exec <<-SCRIPT
        if [[ -s "$HOME/.rvm/scripts/rvm" ]] ; then
          source "$HOME/.rvm/scripts/rvm"
          alias sudo=rvmsudo
          which ruby ||
            rvm install 1.9.3
        elif [[ -s "/usr/local/rvm/scripts/rvm" ]] ; then
          source "/usr/local/rvm/scripts/rvm"
          alias sudo=rvmsudo
          which ruby ||
            rvm install 1.9.3
        else
          dpkg --status ruby1.9.3 > /dev/null ||
            (time sudo apt-get update &&
             time sudo apt-get install ruby1.9.3 -y)
        fi

        dpkg --status avahi-daemon > /dev/null ||
          (time sudo apt-get update &&
           time sudo apt-get install \
             avahi-daemon libavahi-compat-libdnssd-dev -y &&
           time sudo insserv avahi-daemon)

        if ! which whipped-cream; then
          if [ -d /tmp/pkg ]; then
            find /tmp/pkg | tail -n 1 | xargs -I {} \
              sudo gem install {} --no-ri --no-rdoc
          else
            time sudo gem install whipped-cream --no-ri --no-rdoc --pre
          fi
        fi

        mkdir -p ~/whipped-cream/
      SCRIPT
    end

    def copy_plugin
      scp_copy plugin_filename, "whipped-cream/#{plugin_filename}"
    end

    def kill_all_plugins
      ssh_exec 'sudo pkill -9 -f whipped-cream'
    end

    def run_plugin
      ssh_exec <<-SCRIPT
        if [[ -s "$HOME/.rvm/scripts/rvm" ]] ; then
          source "$HOME/.rvm/scripts/rvm"
          alias sudo=rvmsudo
        elif [[ -s "/usr/local/rvm/scripts/rvm" ]] ; then
          source "/usr/local/rvm/scripts/rvm"
          alias sudo=rvmsudo
        fi
        cd ~/whipped-cream
        sudo whipped-cream start #{plugin_filename} --daemonize
      SCRIPT
    end

    def scp_copy(local, remote)
      puts "Copying #{local} to pi@#{pi_address}:#{remote}"
      scp.upload! local, remote
    end

    def ssh_exec(command)
      command = command.prepend("set -ex\n")

      ssh.open_channel do |channel|
        channel.exec command do |process|
          process.on_data do |_, data|
            $stdout.print data
          end

          process.on_extended_data do |_, _, data|
            $stderr.print data
          end
        end
      end.wait
    end
    # :nocov:
  end
end
