module CommLogistics::Modules::ReceivableUtil
  include CommLogistics::Const::Code
  include CommLogistics::Const::Error
  
  #== payment_dateとencachement_dateを取得する
  #[payment] 支払い条件
  #[cutoff_date] 
  # * 戻り値
  #[payment_date]
  #[encachement_date]
  def get_receivable_dates(payment, cutoff_date, need_encachement=true)
    #if payment.payment_type_code.blank? or payment.payment_month_code.blank? or payment.payment_date_code.blank?
    #  raise UserOperationError, LOEMJ0013+LOEMD0015
    #end
    payment_date = nil
    encachement_date = nil
    if payment[:cutoff_type_code] == MCODE_CUTOFF_1_WEEKLY || payment[:cutoff_type_code] == MCODE_CUTOFF_2_WEEKLY || payment[:cutoff_type_code] == MCODE_CUTOFF_DAYLY
      #payment_date = cutoff_date + (payment[:payment_site] || 0)
      payment_date = get_payment_date_site_ahead_for_date(cutoff_date, payment[:payment_site])
      #encachement_date = need_encachement ? payment_date + (payment[:bill_site] || 0) : nil
      encachement_date = need_encachement ? get_payment_date_site_ahead_for_date(payment_date, payment[:bill_site]) : nil
    elsif payment[:cutoff_type_code] == MCODE_CUTOFF_1_MONTHLY || payment[:cutoff_type_code] == MCODE_CUTOFF_2_MONTHLY || payment[:cutoff_type_code] == MCODE_CUTOFF_3_MONTHLY
      payment_date = get_payment_date_site_ahead(cutoff_date, (payment[:payment_site] || 0))
      encachement_date = need_encachement ? get_payment_date_site_ahead(payment_date, (payment[:bill_site] || 0)) : nil
    end
#    day = date_code_to_day(payment.payment_date_code)
#    tmp_date = (cutoff_date >> payment.payment_month_code.to_i)
#    payment_date = Date.new(tmp_date.year, tmp_date.month, day)
#    encachement_date = need_encachement ? get_encachement_date(payment_date, payment) : nil
    return payment_date, encachement_date
  end
  
  #== paymentを決定する
  #[payments] 支払い条件配列
  #[total] 金額（省略された場合は最高金額条件）
  # * 戻り値
  #[payment] 支払い条件
  def get_match_payment(payments, total=nil, total_without_duty=nil)
    if total
      return get_match_payment_real(payments, total, total_without_duty)
    end
    return get_largest_payments(payments)
  end
  
  def get_match_payment_real(payments, total, total_without_duty)#paymentsテーブルはクビになったので、paymentsにはハッシュが詰まっている
    Rails.logger.debug("□DEBUG:total:"+total.inspect)
    Rails.logger.debug("□DEBUG:total_without_duty:"+total_without_duty.inspect)
    match_payment, default_payment = nil,nil
    payments.each do |payment|
      condition_price = payment[:payment_condition_price]
      condition_code = payment[:payment_condition_code]
      tmp_total = payment[:payment_condition_duty_type_code]==MCODE_PRICE_DUTY_TYPE_EXC ? total_without_duty : total
      # 金額から条件を返す
      case condition_code
      when nil
        default_payment = payment
      when MCODE_PAYMENT_COND_EQUAL_MORE
        if tmp_total >= condition_price
          if !match_payment ||  match_payment[:payment_condition_price] < condition_price
            match_payment = payment
          end
        end
      when MCODE_PAYMENT_COND_MORE
        if tmp_total > condition_price
          if !match_payment ||  match_payment[:payment_condition_price] < condition_price
            match_payment = payment
          end
        end
      end
    end
    unless match_payment
      match_payment = default_payment
    end
    Rails.logger.debug("□DEBUG:match_payment:"+match_payment.inspect)
    return match_payment
  end
  
  def get_largest_payments(payments)
    max = payments.first
    payments[1..-1].each do |payment|
      max_price =  max[:payment_condition_price] || 0
      target_price =  payment[:payment_condition_price] || 0
      if max_price < target_price
        max = payment
      end
    end
    Rails.logger.debug("□DEBUG:max payment:"+max.inspect)
    return max
  end
  
#  def get_encachement_date(payment_date, payment)
#    result = Marshal.load(Marshal.dump(payment_date))
#    if payment.payment_type_code == MCODE_PAYMENT_TYPE_BILL
#      result >>= payment.encach_month_code
#      result = Date.new(result.year, result.month, date_code_to_day(payment.encach_date_code))
#    end
#    return result
#  end
  
  #== 支払い条件定数
#  PAY_CONDITION_LESS = 1
#  PAY_CONDITION_EQAL_LESS = 2
#  PAY_CONDITION_EQAL_MORE = 3
#  PAY_CONDITION_MORE = 4
  
  #== 支払い条件取得
  # * 支払い条件を取得して分解する
  #  * コードは下一桁が1から順に 未満、以下、以上、超え を表すらしい
  #  * コードから下一桁を除いた部分*10000（１万）で金額になるみたい
  #
#  def get_payment_condition(payment)
#    code = payment.payment_condition_code
#    unless code
#      return nil, nil
#    end
#    payment_condition = code.to_s
#    len = payment_condition.length
#    amount = payment_condition[0, (len - 1)]
#    condition = payment_condition[(len - 1), 1]
#    return (amount.to_i * 10000), condition.to_i
#  end
  
#  def date_code_to_day(code)
#    return  (code == MCODE_CUTOFF_EOM) ? (-1) : code
#  end
  
  #基準日(cutoff_dateやpayment_date)からsite日分先の日付を求める
  def get_payment_date_site_ahead(base_date, site)
    ahead = site - (30 - (base_date.to_s == base_date.end_of_month.to_s ? 30 : base_date.day))
    day = ahead % 30
    month = ((ahead - day) / 30) + (day==0 ? 0 : 1)
    
    tmp_date = base_date >> month
    return Date.new(tmp_date.year, tmp_date.month, day==0 ? -1 : day)
  end
  
  #基準日からsite日分先を求める(weeklyとdayly用)
  def get_payment_date_site_ahead_for_date(base_date, site)
    require 'config/site_config'
    $INCLUDE_WEEKEND_FOR_PAYMENT ||= false
    if $INCLUDE_WEEKEND_FOR_PAYMENT #土日をカウントする場合はそのまま足し算
      return base_date + (site || 0)
    else
      tmp_site = (site || 0)
      while tmp_site > 0 do
        base_date = base_date + 1
        unless base_date.wday==0 || base_date.wday==6 #土曜と日曜はカウントしない
          tmp_site = tmp_site - 1 
        end
      end
      return base_date
    end
  end
end