# PDF-O-Matic is copyright (c) 2009, Brett Neumeier.
#
# PDF-O-Matic may be used under the terms of the GPL.  See
# COPYING.GPL, provided in this distribution, for full details.
#
# DOJ and CompNet Design, Inc., are granted a perpetual license to
# use, extend, modify, and redistribute the PDF-O-Matic software as
# they wish, without restriction.

require 'pdf_helpers'
require 'item_box'

class SkillBox < ItemBox

  class SkillBoxItem < ItemBoxItem
    def initialize(pdf, item)
      super(pdf, item)
      @cost = item['cost'] || ''
      @roll = item['roll'] || ''
    end
    attr_reader :cost, :roll
  end

  class SkillItem < SkillBoxItem
    def initialize(pdf, skill)
      super
      @text = cleanup_string(skill_text(skill))
    end

    def skill_text(skill)
      t = skill_desc(skill) || ''
      t = skill['name'] + ': ' + t if skill['name']
      t = skill['prefix'] + ' ' + t if skill['prefix']
      t.sub(/ *\([0-9]+ Active Points\)/,'')
    end

    def skill_desc(sk)
      case sk['xmlid']
      when 'PENALTY_SKILL_LEVELS'
        sk['text'].sub(/Penalty Skill Levels:/,'').strip
      else
        sk['text']
      end
    end
  end

  class MartialArtItem < SkillBoxItem
    def initialize(pdf, art)
      super
      @text = cleanup_string(martial_art_text(art))
    end

    def martial_art_text(art)
      case art['xmlid']
      when 'GENERIC_OBJECT'
        display = 'Martial Arts: ' + art['alias']
      when 'MANEUVER'
        display = maneuver_text(art)
      else
        display = art['text']
      end
      display = art['prefix'] + ' ' + display if art['prefix']
      display
    end

    def maneuver_text(maneuver)
      if maneuver['alias'] != maneuver['display']
        maneuver['alias'] + ' (' + maneuver['display'] + ')'
      else
        maneuver['alias']
      end
    end
  end

  class PerkItem < SkillBoxItem
    def initialize(pdf, perk)
      super
      @text = cleanup_string(perk_text(perk))
    end

    def perk_text(perk)
      t = perk['alias'].to_s
      if perk['xmlid'] == 'FAVOR'
        t += ": #{perk['name']}"
      elsif perk['xmlid'] == 'CUSTOMPERK'
        t = perk['name'] + ': ' + t if perk['name']
      else
        t += ": #{perk['input']}" if perk['input']
        t += " (#{perk['name']})" if perk['name']
      end
      if perk['xmlid'] == 'MONEY' && perk['option']
        t += ": #{perk['option']}"
      else
        t += " #{perk['option']}"
      end
      roll = perk['roll']
      if Enumerable === perk['adders']
        if perk['xmlid'] == 'CONTACT'
          t += ' (Contact has '
          t += perk['adders'].map { |a|
            if a['xmlid'] == 'USEFUL'
              a['option_alias']
            elsif a['xmlid'] == 'GENERIC_OBJECT'
              nil
            else
              a['alias'].sub(/Contact has /,'')
            end
          }.compact.join(', ')
          t += ')'
        elsif perk['xmlid'] == 'FRINGE_BENEFIT'
          aliases = perk['adders'].map { |a| a['alias'] }.join(', ')
          t += " (#{aliases})"
        else
          perk['adders'].each { |a|
            if a['xmlid'] == 'HOWWIDE'
              t += " (#{a['option_alias']})"
            end
            # Reputation rolls are stuck in an Adder.  Handle this
            # with a smelly side effect.
            @roll = a['option'] if a['xmlid'] == 'HOWWELL'
          }
        end
      end
      if perk['xmlid'] == 'REPUTATION'
        t += " +#{perk['levels']}/+#{perk['levels']}d6"
      end
      t.squeeze(' ')
    end
  end

  class TalentItem < SkillBoxItem
    def initialize(pdf, talent)
      super
      @text = cleanup_string(talent_text(talent))
    end

    def talent_text(talent)
      t = talent['text']
      t = talent['name'] + ': ' + t if talent['name']
      t
    end
  end

  def add_all(character)
    [ 'skill', 'martial_art', 'perk', 'talent' ].each { |category|
      next unless Enumerable === character["#{category}s"]
      character["#{category}s"].each { |item|
        send("add_#{category}".to_sym, item)
      }
    }
    self
  end

  def add_item(item, type)
    if item['separator']
      items << SeparatorItem.new
    else
      possibly_add_separator(type)
      items << type.new(pdf, item)
    end
  end

  # If the most-recently-added item is of a different type than
  # the item being added, put a separator in. This separates
  # skills from martial arts and so on.
  def possibly_add_separator(type)
    return unless items.size > 0
    previous_item = items.last
    return if previous_item.class == SeparatorItem
    unless [ previous_item.class, SeparatorItem ].include?(type)
      items << SeparatorItem.new
    end
  end

  def add_skill(skill)
    add_item(skill, SkillItem)
  end

  def add_martial_art(art)
    add_item(art, MartialArtItem)
  end

  def add_perk(perk)
    add_item(perk, PerkItem)
  end

  def add_talent(talent)
    add_item(talent, TalentItem)
  end

  def contents
    'skill'
  end

end
