# Responsible for creating posts and topics
#
require_dependency 'rate_limiter'

class PostCreator

  # Errors when creating the post
  attr_reader :errors

  # Acceptable options:
  #
  #   raw                     - raw text of post
  #   image_sizes             - We can pass a list of the sizes of images in the post as a shortcut.  
  #
  #   When replying to a topic:
  #     topic_id              - topic we're replying to
  #     reply_to_post_number  - post number we're replying to
  #
  #   When creating a topic:
  #     title                 - New topic title
  #     archetype             - Topic archetype
  #     category              - Category to assign to topic
  #     target_usernames      - comma delimited list of usernames for membership (private message)
  #     meta_data             - Topic meta data hash
  def initialize(user, opts)
    @user = user    
    @opts = opts
    raise Discourse::InvalidParameters.new(:raw) if @opts[:raw].blank?
  end

  def guardian
    @guardian ||= Guardian.new(@user)
  end

  def create
    topic = nil
    post = nil

    Post.transaction do
      if @opts[:topic_id].blank?
        topic_params = {title: @opts[:title], user_id: @user.id, last_post_user_id: @user.id}
        topic_params[:archetype] = @opts[:archetype] if @opts[:archetype].present?

        guardian.ensure_can_create!(Topic)

        category = Category.where(name: @opts[:category]).first
        topic_params[:category_id] = category.id if category.present?
        topic_params[:meta_data] = @opts[:meta_data] if @opts[:meta_data].present?

        topic = Topic.new(topic_params)
        
        if @opts[:archetype] == Archetype.private_message

          usernames = @opts[:target_usernames].split(',')
          User.where(:username => usernames).each do |u|

            unless guardian.can_send_private_message?(u)
              topic.errors.add(:archetype, :cant_send_pm)
              @errors = topic.errors
              raise ActiveRecord::Rollback.new
            end

            topic.topic_allowed_users.build(user_id: u.id)
          end
          topic.topic_allowed_users.build(user_id: @user.id)
        end

        unless topic.save
          @errors = topic.errors
          raise ActiveRecord::Rollback.new 
        end
      else
        topic = Topic.where(id: @opts[:topic_id]).first
        guardian.ensure_can_create!(Post, topic)
      end

      post = topic.posts.new(raw: @opts[:raw], 
                             user: @user,
                             reply_to_post_number: @opts[:reply_to_post_number])
      post.image_sizes = @opts[:image_sizes] if @opts[:image_sizes].present?
      unless post.save
        @errors = post.errors
        raise ActiveRecord::Rollback.new 
      end

      # Extract links      
      TopicLink.extract_from(post)
    end

    post
  end

  # Shortcut
  def self.create(user, opts)
    PostCreator.new(user, opts).create    
  end

end