# Core SVG data for the trident specification sheet.
#
# This class should never need to be called directly.
# @private
class USPSFlags::Core::TridentSpec
  def initialize(fly: 24, unit: "in")
    @trident_config = USPSFlags.configuration.trident
    configure_sizes(fly)
    configure_labels(unit)
  end

  def svg
    svg = spec_header

    box_left   = (USPSFlags::Config::BASE_FLY*27/32)/2
    box_right  = (USPSFlags::Config::BASE_FLY*37/32)/2
    box_top    = USPSFlags::Config::BASE_HOIST/4
    box_bottom = USPSFlags::Config::BASE_HOIST*3/4
    svg << short_trident(box_top, box_bottom, box_left, box_right)

    box_top    = USPSFlags::Config::BASE_HOIST*3/16
    box_bottom = USPSFlags::Config::BASE_HOIST*13/16
    svg << delta_trident(box_top, box_bottom, box_left, box_right)

    box_top    = USPSFlags::Config::BASE_HOIST/8
    box_bottom = USPSFlags::Config::BASE_HOIST*7/8
    svg << circle_trident(box_top, box_bottom, box_left, box_right)
    svg << long_trident(box_top, box_bottom, box_left, box_right)

    svg
  end

  private
  def configure_sizes(fly)
    @fly = Rational(fly)
    get_hoist_from_fly(@fly)
    configure_hoist_fraction
    configure_fly_fraction
  end

  def get_hoist_from_fly(fly)
    hoist = (fly*Rational(2,3))
    @hoist = if hoist == hoist.to_i
      hoist.to_i
    else
      hoist
    end
  end

  def configure_hoist_fraction
    @hoist_fraction = ""
    if @hoist == @hoist.to_i
      @hoist = @hoist.to_i
    else
      @hoist, @hoist_fraction = @hoist.to_simplified_a
    end
  end

  def configure_fly_fraction
    @fly_fraction = ""
    if @fly == @fly.to_i
      @fly = @fly.to_i
    else
      @fly, @fly_fraction = @fly.to_simplified_a
    end
  end

  def configure_labels(unit)
    @label_font_size = if Math.sqrt(@fly) > 24
      USPSFlags::Config::BASE_FLY * Math.log(24, Math.sqrt(@fly)) / 60
    else
      USPSFlags::Config::BASE_FLY / 60
    end

    @unit_text = unit.nil? ? "" :  "#{unit}"
    @unit = unit

    configure_barb_label
  end

  def configure_barb_label
    barb_label = Rational(@trident_config[:main_point_barb]) * @fly / USPSFlags::Config::BASE_FLY
    @barb_label = if barb_label == barb_label.to_i
      "#{barb_label.to_i}#{@unit_text}"
    else
      "#{barb_label.to_simplified_s}#{@unit_text}"
    end
  end

  def spec_header
    <<~SVG
      <!-- Field -->
      #{USPSFlags::Core.field}

      <!-- Specification Heading Information -->
      <g>
        <style><![CDATA[tspan.heading{font-size: 50%;}]]></style>
        <text x="#{USPSFlags::Config::BASE_FLY/2}" y="#{USPSFlags::Config::BASE_HOIST*3/40}" font-family="sans-serif" font-size="#{USPSFlags::Config::BASE_HOIST/20}px" font-weight="bold" fill="#041E42" text-anchor="middle">United States Power Squadrons<tspan class="heading" dy ="-#{USPSFlags::Config::BASE_HOIST/50}">®</tspan></text>
      </g>
      <text x="#{USPSFlags::Config::BASE_FLY/2}" y="#{USPSFlags::Config::BASE_HOIST/8}" font-family="sans-serif" font-size="#{USPSFlags::Config::BASE_HOIST/30}px" fill="#041E42" text-anchor="middle">Officer Flag Trident Specification</text>
      <text x="#{USPSFlags::Config::BASE_FLY/2}" y="#{USPSFlags::Config::BASE_HOIST*2/11}" font-family="sans-serif" font-size="#{USPSFlags::Config::BASE_HOIST/40}px" fill="#041E42" text-anchor="middle">All measurements are relative to a field with</text>
      <g>
        <style><![CDATA[tspan.title{font-size: #{USPSFlags::Config::FRACTION_SCALE*9/10}%;}]]></style>
        <text x="#{USPSFlags::Config::BASE_FLY/2}" y="#{USPSFlags::Config::BASE_HOIST*4/19}" font-family="sans-serif" font-size="#{USPSFlags::Config::BASE_HOIST/40}px" fill="#041E42" text-anchor="middle">fly of #{@fly} <tspan class="title">#{@fly_fraction}</tspan> #{@unit_text} and hoist of #{@hoist} <tspan class="title">#{@hoist_fraction}</tspan> #{@unit_text}.</text>
      </g>
      <text x="#{USPSFlags::Config::BASE_FLY/2}" y="#{USPSFlags::Config::BASE_HOIST/4}" font-family="sans-serif" font-size="#{USPSFlags::Config::BASE_HOIST/40}px" fill="#041E42" text-anchor="middle">Measurements not specified are the same as on the short trident.</text>
    SVG
  end

  def short_trident(box_top, box_bottom, box_left, box_right)
    <<~SVG
      <!-- Short Trident -->
      <g transform="translate(-#{USPSFlags::Config::BASE_FLY*14/80},#{USPSFlags::Config::BASE_HOIST*9/32})"><g transform="scale(0.7)">
        #{trident_heading(:s)}

        #{USPSFlags::Core::Trident.new(:s).svg}

        <!-- Boundary box -->
        <rect x="#{box_left}" y="#{box_top}" width="#{box_right-box_left}" height="#{USPSFlags::Config::BASE_HOIST/2}" stroke="#666666" stroke-width="#{USPSFlags::Config::BASE_FLY/600}" stroke-dasharray="15, 15" fill="none" />

        <!-- Right -->
          #{USPSFlags::Helpers::SpecArrows.vertical(box_right+@trident_config[:bar_width], box_top, box_top+@trident_config[:bar_width]*4/5, box_right, box_right, fly: @fly, unit: @unit)} <!-- Side spike top gap -->
          #{USPSFlags::Helpers::SpecArrows.vertical(box_right+@trident_config[:bar_width], box_top+@trident_config[:bar_width]*4/5, box_top+@trident_config[:bar_width]*9/10*2+@trident_config[:side_point_height]+@trident_config[:side_spike_height], nil, box_right, fly: @fly, unit: @unit)} <!-- Top gap to hash gap -->
          #{USPSFlags::Helpers::SpecArrows.vertical(box_right+@trident_config[:bar_width], box_top+@trident_config[:bar_width]*18/10+@trident_config[:side_point_height]+@trident_config[:side_spike_height], box_top+@trident_config[:bar_width]*28/10+@trident_config[:side_point_height]+@trident_config[:side_spike_height], nil, @trident_config[:center_point]+@trident_config[:hash_width]/2, fly: @fly, unit: @unit)} <!-- Crossbar to hash gap -->

          #{USPSFlags::Helpers::SpecArrows.vertical(box_right+@trident_config[:bar_width], box_top+@trident_config[:bar_width]*28/10+@trident_config[:side_point_height]+@trident_config[:side_spike_height], box_top+@trident_config[:bar_width]*38/10+@trident_config[:side_point_height]+@trident_config[:side_spike_height], nil, @trident_config[:center_point]+@trident_config[:hash_width]/2, fly: @fly, unit: @unit)} <!-- Hash -->
          #{USPSFlags::Helpers::SpecArrows.vertical(box_right+@trident_config[:bar_width], box_top+@trident_config[:bar_width]*38/10+@trident_config[:side_point_height]+@trident_config[:side_spike_height], box_bottom, nil, box_right, fly: @fly, unit: @unit)} <!-- Hash to bottom -->

        <!-- Left -->
          #{USPSFlags::Helpers::SpecArrows.vertical(box_left-@trident_config[:bar_width]*5.25, box_top, box_bottom, box_left, box_left, fly: @fly, unit: @unit)} <!-- Boundary height -->
          #{USPSFlags::Helpers::SpecArrows.vertical(box_left-@trident_config[:bar_width]*0.75, box_top, box_top+@trident_config[:center_point_height], nil, @trident_config[:center_point]-@trident_config[:bar_width], label_offset: -USPSFlags::Config::BASE_FLY/24, label_offset_y: -USPSFlags::Config::BASE_FLY/60, label_align: "middle", fly: @fly, unit: @unit)} <!-- Main point height -->
          #{USPSFlags::Helpers::SpecArrows.vertical(box_left-@trident_config[:bar_width]*1.5, box_top+@trident_config[:bar_width]*4/5, box_top+@trident_config[:bar_width]*4/5+@trident_config[:side_point_height], box_left, box_left+@trident_config[:bar_width], label_offset: -USPSFlags::Config::BASE_FLY/24, label_align: "middle", fly: @fly, unit: @unit)} <!-- Side point height -->

        <!-- Bottom -->
          #{USPSFlags::Helpers::SpecArrows.horizontal(box_bottom+@trident_config[:bar_width], @trident_config[:center_point]-@trident_config[:bar_width]/2, @trident_config[:center_point]+@trident_config[:bar_width]/2, box_bottom, box_bottom, fly: @fly, unit: @unit)} <!-- Bar width -->
          #{USPSFlags::Helpers::SpecArrows.horizontal(box_bottom+@trident_config[:bar_width]*2.5, @trident_config[:center_point]-@trident_config[:hash_width]/2, @trident_config[:center_point]+@trident_config[:hash_width]/2, box_top+@trident_config[:bar_width]*4+@trident_config[:center_point_height]+@trident_config[:side_spike_height], box_top+@trident_config[:bar_width]*4+@trident_config[:center_point_height]+@trident_config[:side_spike_height], fly: @fly, unit: @unit)} <!-- Hash width -->
          #{USPSFlags::Helpers::SpecArrows.horizontal(box_bottom+@trident_config[:bar_width]*4, box_left, box_right, box_bottom, box_bottom, fly: @fly, unit: @unit)} <!-- Boundary width -->

        <!-- Top -->
          #{USPSFlags::Helpers::SpecArrows.horizontal(box_top-@trident_config[:bar_width], box_left, box_left+@trident_config[:bar_width]*3/2, box_top, box_top+@trident_config[:bar_width]*4/5+@trident_config[:side_point_height], label_offset: -USPSFlags::Config::BASE_FLY/60, fly: @fly, unit: @unit)} <!-- Side point width -->
          #{USPSFlags::Helpers::SpecArrows.horizontal(box_top-@trident_config[:bar_width]*2.5, @trident_config[:center_point]-@trident_config[:bar_width], @trident_config[:center_point]+@trident_config[:bar_width], box_top+@trident_config[:center_point_height], box_top+@trident_config[:center_point_height], label_offset: -USPSFlags::Config::BASE_FLY/60, fly: @fly, unit: @unit)} <!-- Main point width -->

        <!-- Overlay -->
          <!-- Main point barb -->
          <line x1="#{@trident_config[:center_point]+@trident_config[:bar_width]/2}" y1="#{box_top+@trident_config[:center_point_height]-@trident_config[:main_point_barb]}" x2="#{@trident_config[:center_point]+@trident_config[:bar_width]*3/2}" y2="#{box_top+@trident_config[:center_point_height]-@trident_config[:main_point_barb]*5}" stroke="#666666" stroke-width="2" stroke-dasharray="5, 5" />
          <line x1="#{@trident_config[:center_point]+@trident_config[:bar_width]/2}" y1="#{box_top+@trident_config[:center_point_height]}" x2="#{@trident_config[:center_point]+@trident_config[:bar_width]*3/2}" y2="#{box_top+@trident_config[:center_point_height]}" stroke="#666666" stroke-width="2" stroke-dasharray="5, 5" />
          <text x="#{@trident_config[:center_point]+@trident_config[:bar_width]*9/8}" y="#{box_top+@trident_config[:center_point_height]-@trident_config[:main_point_barb]}" font-family="sans-serif" font-size="#{USPSFlags::Config::BASE_FLY/100}px" fill="#041E42" text-anchor="left">#{@barb_label}</text>
      </g></g>
    SVG
  end

  def delta_trident(box_top, box_bottom, box_left, box_right)
    <<~SVG
      <!-- Delta Trident -->
      <g transform="translate(#{USPSFlags::Config::BASE_FLY*5/80},#{USPSFlags::Config::BASE_HOIST*9/32})"><g transform="scale(0.7)">
        #{trident_heading(:d)}

        #{USPSFlags::Core::Trident.new(:d).svg}

        <!-- Boundary box -->
        <rect x="#{box_left}" y="#{box_top}" width="#{box_right-box_left}" height="#{USPSFlags::Config::BASE_HOIST*5/8}" stroke="#666666" stroke-width="#{USPSFlags::Config::BASE_FLY/600}" stroke-dasharray="15, 15" fill="none" />

        <!-- Right -->
          #{USPSFlags::Helpers::SpecArrows.vertical(box_right+@trident_config[:bar_width], box_bottom-@trident_config[:delta_from_bottom]-@trident_config[:bar_width]-@trident_config[:delta_gap_height], box_bottom-@trident_config[:delta_from_bottom]-@trident_config[:bar_width], @trident_config[:center_point], @trident_config[:center_point]+@trident_config[:delta_gap_width], fly: @fly, unit: @unit)} <!-- Delta gap height -->
          #{USPSFlags::Helpers::SpecArrows.vertical(box_right+@trident_config[:bar_width], box_bottom-@trident_config[:delta_from_bottom]-@trident_config[:bar_width], box_bottom-@trident_config[:delta_from_bottom], nil, box_right, fly: @fly, unit: @unit)} <!-- Delta width -->
          #{USPSFlags::Helpers::SpecArrows.vertical(box_right+@trident_config[:bar_width], box_bottom-@trident_config[:delta_from_bottom], box_bottom, nil, box_right, fly: @fly, unit: @unit)} <!-- Delta to bottom -->

        <!-- Left -->
          #{USPSFlags::Helpers::SpecArrows.vertical(box_left-@trident_config[:bar_width]*1.5, box_top, box_bottom, box_left, box_left, label_offset: -USPSFlags::Config::BASE_FLY/30, label_offset_y: -USPSFlags::Config::BASE_FLY*2/11, label_align: "middle", fly: @fly, unit: @unit)} <!-- Boundary height -->
      </g></g>
    SVG
  end

  def circle_trident(box_top, box_bottom, box_left, box_right)
    <<~SVG
      <!-- Circle Trident -->
      <g transform="translate(#{USPSFlags::Config::BASE_FLY*23/80},#{USPSFlags::Config::BASE_HOIST*9/32})"><g transform="scale(0.7)">
        #{trident_heading(:stf)}

        #{USPSFlags::Core::Trident.new(:stf).svg}

        #{long_trident_boundary_box(box_top, box_left, box_right)}

        <!-- Right -->
          #{USPSFlags::Helpers::SpecArrows.vertical(box_right+@trident_config[:bar_width], box_top+@trident_config[:crossbar_from_top]+@trident_config[:bar_width]*2, box_top+@trident_config[:crossbar_from_top]+@trident_config[:width], @trident_config[:center_point], @trident_config[:center_point], fly: @fly, unit: @unit)} <!-- Inner circle diameter -->
          #{USPSFlags::Helpers::SpecArrows.vertical(box_right+@trident_config[:bar_width], box_top+@trident_config[:crossbar_from_top]+@trident_config[:width], box_top+@trident_config[:crossbar_from_top]+@trident_config[:bar_width]+@trident_config[:width], nil, @trident_config[:center_point]+@trident_config[:bar_width]/2, fly: @fly, unit: @unit)} <!-- Outer circle diameter -->
          #{USPSFlags::Helpers::SpecArrows.vertical(box_right+@trident_config[:bar_width], box_top+@trident_config[:crossbar_from_top]+@trident_config[:bar_width]+@trident_config[:width], box_bottom, nil, box_right, fly: @fly, unit: @unit)} <!-- Circle to bottom -->

        #{long_trident_left_arrow(box_top, box_bottom, box_left, box_right)}
      </g></g>
    SVG
  end

  def long_trident(box_top, box_bottom, box_left, box_right)
    <<~SVG
      <!-- Long Trident -->
      <g transform="translate(#{USPSFlags::Config::BASE_FLY*40/80},#{USPSFlags::Config::BASE_HOIST*9/32})"><g transform="scale(0.7)">
        #{trident_heading(:n)}

        #{USPSFlags::Core::Trident.new(:n).svg}

        #{long_trident_boundary_box(box_top, box_left, box_right)}

        <!-- Right -->
          #{USPSFlags::Helpers::SpecArrows.vertical(box_right+@trident_config[:bar_width], box_top+@trident_config[:crossbar_from_top]+@trident_config[:bar_width]*3, box_bottom, @trident_config[:center_point]+@trident_config[:hash_width]/2, box_right, fly: @fly, unit: @unit)} <!-- Hash to bottom -->

        #{long_trident_left_arrow(box_top, box_bottom, box_left, box_right)}
      </g></g>
    SVG
  end

  def trident_heading(type_sym)
    type, description = case type_sym
    when :s
      ["Short", "Squadron Officers"]
    when  :d
      ["Delta", "District Officers"]
    when  :stf
      ["Circle", "Staff Commanders Only"]
    when  :n
      ["Long", "National Officers"]
    end
    <<~SVG
      <text x="#{USPSFlags::Config::BASE_FLY/2}" y="#{USPSFlags::Config::BASE_HOIST*1/40}" font-family="sans-serif" font-size="#{USPSFlags::Config::BASE_HOIST/30}px" font-weight="bold" fill="#BF0D3E" text-anchor="middle">#{type}</text>
      <text x="#{USPSFlags::Config::BASE_FLY/2}" y="#{USPSFlags::Config::BASE_HOIST*5/80}" font-family="sans-serif" font-size="#{USPSFlags::Config::BASE_HOIST/40}px" fill="#BF0D3E" text-anchor="middle">#{description}</text>
    SVG
  end

  def long_trident_boundary_box(box_top, box_left, box_right)
    <<~SVG
      <!-- Boundary box -->
        <rect x="#{box_left}" y="#{box_top}" width="#{box_right-box_left}" height="#{USPSFlags::Config::BASE_HOIST*3/4}" stroke="#666666" stroke-width="#{USPSFlags::Config::BASE_FLY/600}" stroke-dasharray="15, 15" fill="none" />
    SVG
  end

  def long_trident_left_arrow(box_top, box_bottom, box_left, box_right)
    <<~SVG
      <!-- Left -->
        #{USPSFlags::Helpers::SpecArrows.vertical(box_left-@trident_config[:bar_width]*1.5, box_top, box_bottom, box_left, box_left, label_offset: -USPSFlags::Config::BASE_FLY/30, label_offset_y: -USPSFlags::Config::BASE_FLY/4.5, label_align: "middle", fly: @fly, unit: @unit)} <!-- Boundary height -->
    SVG
  end
end