module EasyExtensions
  module EasyInlineFragmentStripper

    extend ActiveSupport::Concern

    included do
      def self.strip_inline_images(*args)
        cattr_accessor :inline_fragmet_stripper_options, :inline_fragmet_stripper_attributes
        options = args.extract_options! || {}
        options[:autosave] ||= Proc.new { false }
        self.inline_fragmet_stripper_options = options
        self.inline_fragmet_stripper_attributes = Array(args.shift)

        before_save :strip_inline_image, if: options[:if]
        after_save :save_stripped_images, if: options[:autosave]

      end
    end

    REGEXP = %r(<img.*src=\\?"data:image\/(.+);base64,(.*)\\?"\s?[\\\/]?>)


    def strip_inline_image_for(attribute)
      @stripped_images ||= Array.new
      n = 1
      self.send(attribute).to_s.gsub(REGEXP) do
        ext, data = $1, $2
        t = Tempfile.new(["Image#{n}", ".#{ext}"])
        begin
          t.binmode
          t.write(Base64.decode64(data)) && t.rewind
          filename = "Image#{Time.now.strftime('%Y%m%d%H%M%S')}_#{n}.#{ext}"

          @stripped_images << attach_stripped_image(filename, t, ext)
        ensure
          t.unlink
        end
        n += 1
        "\nattachment:\"#{filename}\"\n"
      end
    end

    def strip_inline_image_for!(attribute)
      self.update_column(attribute, strip_inline_image_for(attribute))
      @stripped_images.compact.map(&:save)
      @stripped_images.clear
    end


    private

    def save_stripped_images
      @stripped_images.compact.map(&:save) if @stripped_images
    end

    def attach_stripped_image(filename, file, extension)
      self.attachments.build(
          :file => file,
          :filename => filename,
          :author => User.current,
          :description => !!EasySetting.value('attachment_description_required') && '*' || '',
          :content_type => "image/#{extension}") if self.respond_to?(:attachments) && self.attachments.respond_to?(:build)
    end

    def strip_inline_image
      stripped_attrs = self.class.inline_fragmet_stripper_attributes.inject({}) do |mem, var|
        mem[var] = strip_inline_image_for(var) if self.send(var).to_s.size > 10.kilobytes
        mem
      end
      # update_columns(stripped_attrs)
      self.attributes = stripped_attrs
    end
  end
end
