#!/usr/bin/ruby
require 'rubygems'
require 'ostruct'
require 'clamp'
require 'logging'
require 'kafo/configuration'
require 'kafo/exceptions'
require 'kafo/parser_cache_writer'
require 'kafo/string_helper'
require 'logger'
require 'yaml'

KafoConfigure = OpenStruct.new
def KafoConfigure.exit(code)
  Kernel.exit(1)
end

module Kafo
  class KafoExportParams < Clamp::Command
    TYPES = %w(md html asciidoc parsercache)

    option ['-c', '--config'], 'FILE', 'Config file for which should we generate params',
           :required => true

    option ['-f', '--format'], 'FORMAT',
           "Format parameters will be written in, valid options: #{TYPES.join(',')}", :default => 'md' do |format|
      format = format.downcase
      raise ArgumentError unless TYPES.include?(format)
      format
    end

    option ['-o', '--output'], 'FILE', 'Output file to write parameters into', :default => '-'

    option '--[no-]parser-cache', :flag, 'Enable or disable the parser cache, disable for fresh results'

    def execute
      KafoConfigure.logger      = Logger.new(STDERR)
      c                         = Configuration.new(config, false)
      KafoConfigure.config      = c
      if KafoConfigure.config.parser_cache
        KafoConfigure.config.parser_cache.force = true if ARGV.include?('--parser-cache')
        KafoConfigure.config.parser_cache.force = false if ARGV.include?('--no-parser-cache')
      end
      KafoConfigure.root_dir    = File.expand_path(c.app[:installer_dir])
      KafoConfigure.module_dirs = c.module_dirs

      if output == '-'
        file = STDOUT
      else
        file = File.open(output, 'w')
      end

      exporter = self.class.const_get(format.capitalize).new(c, file)
      exporter.print_out
    end

    class Writer
      def initialize(config, file)
        @config = config
        @file = file
      end

      def puts(*args)
        @file.puts(*args)
      end
    end

    class Html < Writer
      include StringHelper

      def print_out
        puts '<div id="installer-options">'
        puts '  <table class="table table-bordered table-condensed">'
        header
        puts '    <tbody>'

        @config.modules.sort.each do |mod|
          mod.params.sort.each do |param|
            puts '      <tr>'
            puts "        <td style='white-space:nowrap'>#{parametrize(param)}</td>"
            puts "        <td>#{param.doc.join(' ')}</td>"
            puts '      </tr>'
          end
        end

        puts '    </tbody>'
        puts '  </table>'
        puts '</div>'
      end

      private

      def header
        puts '    <thead>'
        puts '      <tr>'
        puts '        <th>Option</th>'
        puts '        <th>Description</th>'
        puts '      </tr>'
        puts '    </thead>'
      end
    end

    class Asciidoc < Writer
      include StringHelper

      def print_out
        @config.modules.sort.each do |mod|
          puts "Parameters for '#{mod.name}':\n\n"
          mod.params.sort.each do |param|
            puts "#{parametrize(param)}::"
            puts param.doc.join("\n")
            puts "\n"
          end
          puts "\n"
        end
      end
    end

    class Md < Writer
      include StringHelper

      def initialize(*args)
        super
        @max = max_description_length
      end

      def print_out
        puts "| #{('Parameter name').ljust(40)} | #{'Description'.ljust(@max)} |"
        puts "| #{'-'*40} | #{'-' * @max} |"
        @config.modules.sort.each do |mod|
          mod.params.sort.each do |param|
            puts "| #{parametrize(param).ljust(40)} | #{param.doc.join(' ').ljust(@max)} |"
          end
        end
      end

      private

      def header
        @header ||= "| #{'-'*40} | #{'-' * @max} |"
      end

      def max_description_length
        doc_lengths = @config.modules.map { |mod| mod.params.map { |param| param.doc.join(' ').length } }.flatten
        doc_lengths << 52
        doc_lengths.max
      end
    end

    class Parsercache < Writer
      def print_out
        puts Kafo::ParserCacheWriter.write(@config.modules).to_yaml
      end
    end
  end
end

Kafo::KafoExportParams.run