class Charge < ActiveRecord::Base
  belongs_to :charge_set

  validates_numericality_of :chips_used
  validates_numericality_of :chip_cost
  validates_numericality_of :labeling_cost
  validates_numericality_of :hybridization_cost
  validates_numericality_of :qc_cost
  validates_numericality_of :other_cost

  # command-line interface to scrape sbeams array request
  def Charge.command_line_sbeams_import
    require("highline")
    
    ui = HighLine.new
    
    username = ui.ask("Username: ")
    password = ui.ask("Password: ") { |q| q.echo = "x" }
    request_id = ui.ask("Array Request ID: ")

    # ask what lab group to assign charges into
    lab_groups = LabGroup.find(:all)
    
    puts "Lab Groups:\n\n"
    for n in 0..lab_groups.size-1
      puts (n+1).to_s + ". " + lab_groups[n].name + "\n"
    end
    lab_group_number = ui.ask("\n> ")
    lab_group_id = lab_groups[lab_group_number.to_i-1].id

    scrape_array_request(username, password, request_id, lab_group_id)
  end

  # web scrape an array_request view form from SBEAMS
  # using scRUBYt!
  def Charge.scrape_array_request(username, password, request_id, lab_group_id)
    require("scrubyt")

    # scraping module generated by scRUBYt! based on a provided example   
    sbeams_data = Scrubyt::Extractor.define do
      fetch(SiteConfig.sbeams_address + 
           "/cgi/Microarray/SubmitArrayRequest.cgi?TABLE_NAME=MA_array_request&array_request_id=" + 
           request_id)
      fill_textfield("username", username)
      fill_textfield("password", password)
      submit(0)
      fill_textarea("comment", "")
      submit(0)
      
      form("/html/body/p/p", { :generalize => true }) do
        table("/form[1]") do
          contact("/table[1]/tr[1]/td[2]")
          project("/table[1]/tr[2]/td[2]")
          slide_type("/table[1]/tr[4]/td[2]")
          #hybridization_request("/table[1]/tr[7]/td[2]")
          #scanning_request("/table[1]/tr[8]/td[2]")
          request_date("/table[1]/tr[12]/td[2]")
          row("/p/p/table/tr", { :generalize => true }) do
            slideid("/td[2]")
            sample1("/td[3]/font[1]")
            sample2("/td[6]/font[1]")
          end.ensure_presence_of_pattern("slideid")
        end.ensure_presence_of_pattern("slide_index")
      end
    end

    hash = sbeams_data.to_hash
    
    # project/charge info
    project = hash[0]['project']
    project_elements = project.scan(/\A(.*)\ \[(.*)\]/)

    # get rid of enclosing array
    project_elements = project_elements[0]

    # ensure that there project field is encoded how we expect
    if( project_elements.size != 2 || project_elements[0] == nil )
      raise "Couldn't parse the project field"
    end
    
    project_name = project_elements[0]
    project_budget = project_elements[1]    

    # get slide cost
    slide_type = hash[0]['slide_type']
    array_cost = slide_type.scan(/.*\(\ \$(\d+)\ \)/)
    array_cost = array_cost[0][0]

    request_date = hash[0]['request_date']

    # sample name info
    sample1_list = hash[0]['sample1']
    sample1_array = sample1_list.split(/,/)
    sample2_list = hash[0]['sample2']
    sample2_array = sample2_list.split(/,/)
    
    # use the most recently created charge set
    charge_period = ChargePeriod.find(:first, :order => "id DESC")
    
    # if no charge periods exist, make a default one
    if( charge_period == nil )
      charge_period = ChargePeriod.new(:name => "Default Charge Period")
      charge_period.save
    end

    charge_set = ChargeSet.find(:first, :conditions => ["name = ? AND lab_group_id = ? AND budget = ? AND charge_period_id = ?",
                                           project_name, lab_group_id, project_budget, charge_period.id])
    # see if new charge set need to be created
    if(charge_set == nil)  
      charge_set = ChargeSet.new(:charge_period_id => charge_period.id,
                                  :name => project_name,
                                  :lab_group_id => lab_group_id,
                                  :budget => project_budget
                                  )
      charge_set.save
    end

    for n in 0..sample1_array.size-1
      charge = Charge.new(:charge_set_id => charge_set.id,
                          :date => request_date,
                          :description => sample1_array[n] + "_v_" + sample2_array[n],
                          :chips_used => 1,
                          :chip_cost => array_cost,
                          :labeling_cost => 0,
                          :hybridization_cost => 0,
                          :qc_cost => 0,
                          :other_cost => 0)
      charge.save
    end
  end

end
