# Copyright:: (c) Autotelik Media Ltd 2011
# Author ::   Tom Statter
# Date ::     Dec 2012
# License::   MIT
#
# Details::   Helper for creating consistent import/export format
#             of model's attributes/associations
#
require 'datashift/delimiters'

module DataShift

  module ColumnPacker

    include Delimiters
    extend Delimiters

    # Return opposite of text delim - "hello, 'barry'" => '"hello, "barry""'
    def escape_text_delim
      return '"' if text_delim == "\'"
      "\'"
    end

    # Ensure a value is written to CSV correctly
    # TODO: - better ways ?? - see transcoding and String#encode

    def escape_for_csv(value)
      return nil if value.blank?
      text = value.to_s.gsub(text_delim, escape_text_delim).gsub("\n", '\\n')

      text = "#{text_delim}#{text}#{text_delim}" if(text.include?(csv_delimiter) && text.present?)
      text
    end

    # Convert an AR instance to a single column
    #    e.g User  :  ":name = > 'tom', :role => 'developer'"
    #
    # OPTIONS
    #
    #     json:         Export association data in single column in JSON format

    def record_to_column(record, json = false)

      return '' if record.nil? || (record.respond_to?(:each) && record.empty?)

      # :only and :except options can be used to limit the attributes included

      return record.to_json if json # packs associations into single column

      data = []

      if record.respond_to?(:each)
        return '' if record.empty?

        record.each { |r| data << record_to_column(r, json) }

        data.join(multi_assoc_delim).to_s
      else
        record.serializable_hash.each do |name, value|
          text = value.to_s.gsub(text_delim, escape_text_delim)
          data << "#{name}:#{key_value_sep}#{text}"
        end

        "#{attribute_list_start}#{data.join(multi_value_delim)}#{attribute_list_end}"
      end


    end

    # Convert an AR instance to a set of CSV columns
    def record_to_csv(record, options = {})
      csv_data = record.serializable_hash.values.collect { |value| escape_for_csv(value) }

      [*options[:methods]].each { |x| csv_data << escape_for_csv(record.send(x)) if record.respond_to?(x) } if options[:methods]

      csv_data.join( csv_delimiter )
    end

  end
end
