require 'mechanize'

module Smotri # :nodoc:
  class Uploader

    START_URL = 'http://smotri.com/'

=begin rdoc
In order to create a valid uploader instance pass credentials of some registered account.
=end
    def initialize(username, password)
      @username = username
      @password = password
      make_agent
    end

=begin rdoc
Logs into the site using credentials passed to constructor.
Returns true value on success and false value if login failed.
=end
    def login
      @agent.get START_URL
      form = @agent.page.form_with(:id => 'login')
      form.login = @username
      form.password = @password
      form.submit
      login_successful?
    end

=begin rdoc
Checks login status.
Returns true value if logged in and false value otherwise.
=end
    def login_successful?
      !! @agent.page.at('.users-office')
    end

=begin rdoc
Uploads video file and returns video link on success.
On failure returns false value.

  +params+ must contain following values:

  :title        name of the video
  :path         file system path where video file is located

  +params+ may contain following options:

  :category        category name (one of the predefined on the site)
  :keywords        list of tags assigned to video separated by commas
  :description     some info about the video
  :privacy         indicates video visibility and should be "public" or "private" (default)
  :password        set password authentication for video
  :commentable     pass true value in order to allow comments
  :downloadale     pass true to grant video downloading

=end
    def upload(params = {})
      get_upload_page
      if upload_file(params)
        link = video_link
        fill_details(params)
        if navigate_to_edit(link)
          fill_details(params)
        end
        return link
      end
    rescue
      false
    end

    private

    def make_agent
      @agent = Mechanize.new do |a|
        a.user_agent_alias = 'Mac Safari'
        a.max_history = 1
      end
    end

    def get_upload_page
      @agent.page.link_with(:href => %r{/upload}).click
      @agent.get @agent.page.at('//iframe[contains(@src, "upload")]')[:src]
    end

    def upload_file(params)
      form = upload_form
      return false unless form
      form.file_upload_with(:name => 'upload').file_name = params[:path]
      form.title = params[:title]
      form.tags = params[:keywords] if params[:keywords]
      category = form.field_with(:name => 'rubric')
      option = category.options.detect {|opt| opt.text =~ /#{params[:category] || 'nonexistent'}/ } || category.options[1]
      option.select
      form.submit
      @agent.get @agent.page.body.match(/window.parent.parent.location\s*=\s*["']([^'"]+)/)[1]
    end

    def navigate_to_edit(link)
      tries = 0
      loop do
        sleep 5
        @agent.get link
        if edit_link = @agent.page.link_with(:href => %r{/video/edit})
          edit_link.click
          return true
        else
          tries += 1
          if tries > 3
            return false
          else
            sleep rand(15)
          end
        end
      end
    end

    def fill_details(params)
      form = @agent.page.form_with(:id => 'video_edit')
      return unless form
      form.action = @agent.page.uri.to_s
      form.radiobutton_with(:name => 'visible', :value => (params[:privacy] == 'public' ? '0' : '1')).check
      form.description = params[:description]
      if params[:password]
        form.checkbox_with(:name => 'option').check
        form.password = params[:password]
        form.confirm_password = params[:password]
      end
      form.checkbox_with(:name => 'allow_download').send(params[:downloadale] ? :check : :uncheck)
      form.checkbox_with(:name => 'deny_comments').send(params[:commentable] ? :uncheck : :check)
      form.delete_field! 'allow_notify'
      #form.add_field! 'submit_mv_form.x', rand(30)
      #form.add_field! 'submit_mv_form.y', rand(30)
      form.submit
    end

    def upload_form
      @agent.page.form_with :id => 'video_upload'
    end

    def video_link
      if link = @agent.page.at('#videolinktext')
        link[:value]
      end
    end
  end
end

