# frozen_string_literal: true
class MapExportService
  attr_reader :user, :map
  def initialize(user, map)
    @user = user
    @map = map
  end

  def json
    # marshal_dump turns OpenStruct into a Hash
    {
      topics: exportable_topics.map(&:marshal_dump),
      synapses: exportable_synapses.map(&:marshal_dump)
    }
  end

  def csv(options = {})
    CSV.generate(options) do |csv|
      to_spreadsheet.each do |line|
        csv << line
      end
    end
  end

  def xls
    to_spreadsheet
  end

  private

  def topic_headings
    [:id, :name, :metacode, :x, :y, :description, :link, :user, :permission]
  end

  def synapse_headings
    [:topic1, :topic2, :category, :description, :user, :permission]
  end

  def exportable_topics
    visible_topics ||= Pundit.policy_scope!(user, map.topics)
    topic_mappings = Mapping.includes(mappable: [:metacode, :user])
                            .where(mappable: visible_topics, map: map)
    topic_mappings.map do |mapping|
      topic = mapping.mappable
      next nil if topic.nil?
      OpenStruct.new(
        id: topic.id,
        name: topic.name,
        metacode: topic.metacode.name,
        x: mapping.xloc,
        y: mapping.yloc,
        description: topic.desc,
        link: topic.link,
        user: topic.user.name,
        permission: topic.permission
      )
    end.compact
  end

  def exportable_synapses
    visible_synapses = Pundit.policy_scope!(user, map.synapses)
    visible_synapses.map do |synapse|
      next nil if synapse.nil?
      OpenStruct.new(
        topic1: synapse.node1_id,
        topic2: synapse.node2_id,
        category: synapse.category,
        description: synapse.desc,
        user: synapse.user.name,
        permission: synapse.permission
      )
    end.compact
  end

  def to_spreadsheet
    spreadsheet = []
    spreadsheet << ['Topics']
    spreadsheet << topic_headings.map(&:capitalize)
    exportable_topics.each do |topics|
      # convert exportable_topics into an array of arrays
      spreadsheet << topic_headings.map { |h| topics.send(h) }
    end

    spreadsheet << []
    spreadsheet << ['Synapses']
    spreadsheet << synapse_headings.map(&:capitalize)
    exportable_synapses.each do |synapse|
      # convert exportable_synapses into an array of arrays
      spreadsheet << synapse_headings.map { |h| synapse.send(h) }
    end

    spreadsheet
  end
end