#!/usr/bin/ruby

#	Transporter Chief
#	Copyright Gamua GmbH. All Rights Reserved.
#
#	This program is free software. You can redistribute and/or modify it
#	in accordance with the terms of the accompanying license agreement.

require 'optparse'
require 'ostruct'
require 'fileutils'
require 'pathname'
require 'tmpdir'

$script_path = File.expand_path(File.dirname(__FILE__))
$temp_path = Dir.mktmpdir
$ios_deploy_executable = "#{$script_path}/ios-deploy"

def purge_temp
  FileUtils.rm_rf($temp_path)
end

def initialize_temp
  purge_temp
  FileUtils.mkdir($temp_path)
end

def execute(command, verbose)
  if verbose
    system command
  else
    system "#{command} >> /dev/null"
  end
end

def log(message)
  puts "# Transporter chief: #{message}, Sir."
end

def fail(message)
  log message
  purge_temp
  exit 1
end

# prepare the options and their parser
options = OpenStruct.new
options.update_ios_deploy = false
options.verbose = false
options.device_id = nil
option_parser = OptionParser.new do |opts|
  opts.banner = "Usage: #{File.basename(__FILE__)} [options] path_to_app"

  opts.separator ""
  opts.separator "Supported types for path_to_app:\n    *.app (app bundle directory)\n    *.ipa (iPhone application file)"
  opts.separator ""
  opts.separator "Options:"

  opts.on('-d', '--device IDENTIFIER', 'Beam to specific device') do |id|
    options.device_id = id
  end

  opts.on('-u', '--update', 'Update ios-deploy binary to latest version') do
    options.update_ios_deploy = true
  end

  opts.on('-v', '--verbose', 'Redirect logs of ship\'s computer to console') do
    options.verbose = true
  end

  opts.on_tail('-h', '--help', 'Show this message') do
    puts opts
    exit
  end
end

# parse the command line parameters or print the help message
if ARGV.length < 1
  puts option_parser
  exit
else
  option_parser.parse!
end

# update ios-deploy if it's not installed or an update was requested
if options.update_ios_deploy || !File.exist?($ios_deploy_executable)
  initialize_temp

  if File.exist? $ios_deploy_executable
    log "Removing current ios-deploy"
    FileUtils.rm_rf($ios_deploy_executable)
  end

  Dir.chdir($temp_path) do
    log "Fetching latest ios-deploy"
    quiet = options.verbose ? "" : "-q"
    execute("git clone #{quiet} https://github.com/phonegap/ios-deploy.git", options.verbose)
    Dir.chdir("ios-deploy/") do
      log "Compiling ios-deploy"
      execute("xcodebuild", options.verbose)
    end
  end
  FileUtils.mv(File.join($temp_path, "/ios-deploy/build/Release/ios-deploy"), $script_path)
end

# install the app if a valid path was given
path_to_app = ARGV.last()
if path_to_app != nil && File.exist?(path_to_app)
  # deploy the given app/ipa path to the first connected device
  if File.extname(path_to_app) == ".ipa"
    # unzip the ipa to make way to the app bundle - updates path_to_app
    initialize_temp

    log "Extracting app"
    execute("unzip -o '#{path_to_app}' -d #{$temp_path}", options.verbose)
    if $? == 0
      path_to_app = Pathname(File.join($temp_path, "Payload/")).children.first
    else
      fail "Cannot unzip ipa at #{path_to_app}. Run verbose to get a more specific error message"
    end
  end

  if File.extname(path_to_app) == ".app"
    # ios-deploy the app bundle
    device_id_string = options.device_id == nil ? "" : " #{options.device_id}"
    device_id_parameter = options.device_id == nil ? "" : "-i #{options.device_id}"

    log "Beaming app to device#{device_id_string}"
    execute("#{$ios_deploy_executable} #{device_id_parameter} -b '#{path_to_app}'", options.verbose)
    if $? != 0
      fail "Unable to deploy app to device. Run verbose to get a more specific error message"
    end
  else
    # given path is neither an ipa nor an app bundle
    fail "Unknown app type at #{path_to_app}"
  end
end

purge_temp
log "All done"