#!/usr/pkg/bin/ruby26
#--
# Copyright (c) 2008 Ryan Grove <ryan@wonko.com>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
#   * Redistributions of source code must retain the above copyright notice,
#     this list of conditions and the following disclaimer.
#   * Redistributions in binary form must reproduce the above copyright notice,
#     this list of conditions and the following disclaimer in the documentation
#     and/or other materials provided with the distribution.
#   * Neither the name of this project nor the names of its contributors may be
#     used to endorse or promote products derived from this software without
#     specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#++

require 'optparse'
require 'rubygems'

gem 'ramaze', '=2008.06'

require 'ramaze'

module Thoth
  cli_action = :server # :import, :migrate, or :server
  cli_values = {}

  # Parse command-line options.
  begin
    OptionParser.new {|o|
      o.summary_indent = '  '
      o.summary_width  = 24
      o.banner         = "Usage: thoth [options]\n" +
                         "       thoth [info]"

      o.separator ''
      o.separator 'Options:'

      o.on('-a', '--adapter <adapter>',
          'Use the specified Ramaze server adapter.') do |adapter|
        trait[:adapter] = adapter
      end

      o.on('-c', '--config <filename>',
          'Use the specified configuration file.') do |filename|
        trait[:config_file] = File.expand_path(filename)
      end

      o.on('-d', '--daemon <command>', [:start, :stop, :restart],
          'Issue the specified daemon command (start, stop, or',
          'restart).') do |cmd|
        trait[:daemon] = cmd
      end

      o.on('-H', '--home <path>',
          'Use the specified home directory.') do |home|
        unless File.directory?(home)
          abort("Error: home directory not found or not a directory: #{home}")
        end

        HOME_DIR = File.expand_path(home)
      end

      o.on('-i', '--ip <address>',
          'Listen for connections on the specified IP address.') do |address|
        trait[:ip] = address
      end

      o.on('-p', '--port <number>',
          'Listen for connections on the specified port number.') do |port|
        trait[:port] = port.to_i
      end

      o.separator ''

      o.on('--create <path>',
          'Create a new Thoth home directory with a sample',
          'config file.') do |path|
        require 'thoth'

        begin
          create(path)
        rescue => e
          abort("Error: #{e}")
        end

        puts 'Your new Thoth home directory has been created at ' <<
            File.expand_path(path)

        exit
      end

      o.on('--devel',
          'Run Thoth in development mode.') do
        trait[:mode] = :devel
      end

      o.on('--import <module>',
          'Import content from another blog engine using the',
          'specified import module.') do |import_module|
        cli_action = :import
        cli_values[:importer] = import_module
      end
      
      o.on('--irb',
          'Start Thoth within an IRB session.') do
        trait[:irb] = true
      end

      o.on('--log-sql <filename>',
          'Log all SQL queries to the specified file.') do |filename|
        trait[:sql_log] = File.expand_path(filename)
      end

      o.on '--migrate [version]',
          'Migrate the database to the specified schema version,',
          'or to the latest version if not specified.' do |version|
        cli_action = :migrate
        cli_values[:schema_version] = version
      end

      o.separator ''
      o.separator 'Info:'

      o.on_tail('-h', '--help',
          'Display usage information (this message).') do
        require 'thoth'

        puts "#{APP_NAME} v#{APP_VERSION} <#{APP_URL}>"
        puts "#{APP_COPYRIGHT}"
        puts
        puts o
        puts
        puts 'Default Directories:'
        puts "  public: #{PUBLIC_DIR}"
        puts "    view: #{VIEW_DIR}"
        exit
      end

      o.on_tail('-v', '--version',
          'Display version information.') do
        require 'thoth'

        puts "#{APP_NAME} v#{APP_VERSION} <#{APP_URL}>"
        puts "#{APP_COPYRIGHT}"
        puts
        puts "#{APP_NAME} comes with ABSOLUTELY NO WARRANTY."
        puts
        puts "This program is open source software distributed under the BSD license. For"
        puts "details, see the LICENSE file contained in the source distribution."
        exit
      end
    }.parse!(ARGV)
  rescue => e
    abort("Error: #{e}")
  end

  require 'thoth'

  Config.load(trait[:config_file])

  if trait[:irb]
    # Avoid passing args to IRB.
    ARGV.clear

    require 'irb'
    require 'irb/completion'

    ENV['IRBRC'] = '.irbrc' if File.exist?('.irbrc')
    IRB.start
  end

  case cli_action
  when :import
    require 'thoth/importer'

    begin
      Importer.load_importer(cli_values[:importer]).run
    rescue LoadError => e
      abort("Error: #{e}")
    end

  when :migrate
    schema_version = cli_values[:schema_version]

    if !schema_version.nil? && schema_version.to_i == 0
      puts 'WARNING: Migrating to schema version 0 will delete your Thoth database. This'
      puts 'action cannot be undone. Are you sure you want to continue? (y/n)'
      print '> '

      exit unless STDIN.gets.strip =~ /^y(?:es)?/i
      puts
    end

    begin
      open_db
      Sequel::Migrator.apply(@db, LIB_DIR/:migrate, schema_version.nil? ? nil :
          schema_version.to_i)
    rescue => e
      abort("Error: #{e}")
    else
      puts "Migration complete."
    end

  when :server
    trait[:adapter] ||= Config.server.adapter
    trait[:ip]      ||= Config.server.address
    trait[:port]    ||= Config.server.port
    trait[:pidfile]   = HOME_DIR/"thoth_#{trait[:ip]}_#{trait[:port]}.pid"

    begin
      send(trait[:daemon] || :run)
    rescue SchemaError => e
      abort("Error: #{e}")
    end

  else
    abort("Error: unknown action: #{cli_action}")
  end
end
