# encoding: utf-8
#
# Redmine - project management software
# Copyright (C) 2006-2013  Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

module UserScoreHelper
  def calculate_collaboration_count(user)
    issue_c = 0
    issues = Issue.where('author_id = ?', user.id)
    issues.each do |issue|
      issue_c = issue_c + issue.journals.where("user_id <> ?", user.id).count
    end
    issue_c = issue_c + Journal.where("user_id = ?", user.id).count
    ############################
    memos = Memo.where('author_id = ? AND parent_id IS NOT NULL', user.id)
    
    memos.each do |m|
      if Memo.find(m.parent_id).author.id != user.id
        issue_c = issue_c + 1
      else
        issue_c = issue_c - 1
      end
    end
    
    
    pmemos = Memo.where('author_id = ? AND parent_id IS NULL', user.id)
    pmemos.each do |pm|
      issue_c = issue_c + pm.replies_count
    end
    ############################
    
    issue_c = issue_c + JournalsForMessage.where('user_id = ? AND reply_id IS NOT NULL AND reply_id <> ?', user.id, user.id).count + JournalsForMessage.where('reply_id = ? AND user_id <> ?', user.id, user.id).count
    
    
    
    return issue_c
  end

  def calculate_influence_count(user)
    watcher_count = Watcher.where("watchable_type = 'principal' AND watchable_id = ?", user.id).count
  end




  def calculate_skill_count(user)
    
    praise_count_l0 = 0
    praise_count_l1 = 0
    praise_count_l2 = 0
    tread_count_l0 = 0
    tread_count_l1 = 0
    tread_count_l2 = 0
    issues = Issue.where('author_id = ?', user.id)   
    issues.each do |i|
      pts = PraiseTread.where('praise_tread_object_id = ?', i.id)
      pts.each do |p|
        templevel = calculate_level(User.find(p.user_id))

        if templevel.to_i == 0
          if p.praise_or_tread == 1
            praise_count_l0 = praise_count_l0 + 1
          else
            tread_count_l0 = tread_count_l0 + 1            
          end
        end
        if templevel.to_i == 1
          if p.praise_or_tread == 1
            praise_count_l1 = praise_count_l1 + 1
          else
            tread_count_l1 = tread_count_l1 + 1
          end
        end
        if templevel.to_i == 2
          if p.praise_or_tread == 1
            praise_count_l2 = praise_count_l2 + 1
          else
            tread_count_l2 + tread_count_l2 + 1
          end
        end
      end
    end



    
    bids = Bid.where('author_id = ?', user.id)
    bids.each do |b|
      ptcs = PraiseTread.where('praise_tread_object_id = ?', b.id)
      ptcs.each do |p|
        templevel = calculate_level(User.find(p.user_id))

        if templevel.to_i == 0
          if p.praise_or_tread == 1
            praise_count_l0 = praise_count_l0 + 1
          else
            tread_count_l0 = tread_count_l0 + 1            
          end
        end
        if templevel.to_i == 1
          if p.praise_or_tread == 1
            praise_count_l1 = praise_count_l1 + 1
          else
            tread_count_l1 = tread_count_l1 + 1
          end
        end
        if templevel.to_i == 2
          if p.praise_or_tread == 1
            praise_count_l2 = praise_count_l2 + 1
          else
            tread_count_l2 + tread_count_l2 + 1
          end
        end
      end
    end
    
    contests = Contest.where('author_id = ?', user.id)
    contests.each do |c|
      ptcs = PraiseTread.where('praise_tread_object_id = ?', c.id)
      ptcs.each do |p|
        templevel = calculate_level(User.find(p.user_id))

        if templevel.to_i == 0
          if p.praise_or_tread == 1
            praise_count_l0 = praise_count_l0 + 1
          else
            tread_count_l0 = tread_count_l0 + 1            
          end
        end
        if templevel.to_i == 1
          if p.praise_or_tread == 1
            praise_count_l1 = praise_count_l1 + 1
          else
            tread_count_l1 = tread_count_l1 + 1
          end
        end
        if templevel.to_i == 2
          if p.praise_or_tread == 1
            praise_count_l2 = praise_count_l2 + 1
          else
            tread_count_l2 + tread_count_l2 + 1
          end
        end 
      end     
    end
    
    
    
#    case level
#      when 0 skill_score = praise_count - 0.5 * tread_count
#      when 1 skill_score = 2 * praise_count - 1.5 * tread_count
#      when 2 skill_socre = 3 * praise_count - 2.5 * tread_count
#      when 3 skill_socre = 4 * praise_count - 3.5 * tread_count
#      when 4 skill_socre = 5 * praise_count - 4.5 * tread_count
#    end

    skill_score = 2 * praise_count_l0.to_f + 3 * praise_count_l1.to_f + 4 * praise_count_l2.to_f
                  - 1 * tread_count_l0.to_f - 1.5 * tread_count_l1.to_f - 2 * tread_count_l2.to_f
    
    tread_user_count = PraiseTread.where('praise_or_tread = ? AND user_id = ?', 0, user.id).count
    
    skill_score = skill_score.to_f - tread_user_count.to_f







    return skill_score
    
    
    
  end
  
  def calculate_level(user)
    commit_count = user.changesets.count
    max_praise_num = 0
    
    
    issues = Issue.where('author_id = ?', user.id)   
    issues.each do |i|
      ptcs = PraiseTreadCache.where('object_id = ?', i.id)
      ptcs.each do |p|
        if p.praise_num.to_i > max_praise_num.to_i
          max_praise_num = p.praise_num
        end
      end
    end
    
    bids = Bid.where('author_id = ?', user.id)
    bids.each do |b|
      ptcs = PraiseTreadCache.where('object_id = ?', b.id)
      ptcs.each do |p|
        if p.praise_num.to_i > max_praise_num.to_i
          max_praise_num = p.praise_num
        end
      end
    end
    
    contests = Contest.where('author_id = ?', user.id)
    contests.each do |c|
      ptcs = PraiseTreadCache.where('object_id = ?', c.id)
      ptcs.each do |p|
        if p.praise_num.to_i > max_praise_num.to_i
          max_praise_num = p.praise_num
        end
      end     
    end
    
    
    best_answer_num = 0
    
    isManager = 0
    members = Member.where('user_id = ?', user.id)
    members.each do |m|
      roles = m.member_roles
      roles.each do |r|
        if r.role_id == 3
          isManager = 1
        end
      end
    end
    
    level = 0
    
    if max_praise_num > 4
      level = 1
    end
    if commit_count > 0 and commit_count < 101
      level = 1
    end  
    if commit_count > 100 or isManager == 1
      level = 2
    end
    
    return level
    
  end

  def calculate_activity_count(user)
    # commit_count = user.changesets.count
    # issue_details_count = 0
    # issues = Issue.where('assigned_to_id = ?', user.id)
    # issues.each do |issue|
    # change_count = issue.journals.where("prop_key = ?", "done_ratio").count
    # issue_details_count = change_count + issue_details_count
    # end
    # file_count = user.file_commit.count
    # issue_count = Issue.where('author_id = ?', user.id).count
    #f = user.user_score.file
    #i = user.user_score.issue
    #f_max = UserScore.find_max_file
    #f_min = UserScore.find_min_file
    #i_max = UserScore.find_max_issue
    #i_min = UserScore.find_min_issue
    #score = 100 * ((f - f_min)/(f_max - f_min) + (i - i_min)/(i_max - i_min))
  end

  def calculate_file(user)
    file_count = user.file_commit.count
    issue_count = Issue.where('author_id = ?', user.id).count
    return (file_count + issue_count)
  end

  def calculate_issue(user)
    commit_count = user.changesets.count
     
    issue_details_count = 0
    issues = Issue.where('assigned_to_id = ?', user.id)
    
    change_count = 0
    issues.each do |issue|
      js = issue.journals
      js.each do |j|
        change_count = change_count + j.details.where("prop_key = ?", "done_ratio").count
      end
    
      
      issue_details_count = change_count + issue_details_count
    end
    
    return (commit_count + issue_details_count)
    
  end
  
  def calculate_user_score(user)
    collaboration = calculate_collaboration_count(user)
    influence = calculate_influence_count(user)
    skill = calculate_skill_count(user)
    activity = calculate_activity_count(user)
    file = calculate_file(user)
    issue = calculate_issue(user)
    level = calculate_level(user)
    #user.user_score << UserScore.new(:collaboration => collaboration, :influence => influence, :skill => skill,
    #                                 :activity => activity, :file => file, :issue => issue, :level => level)
    UserScore.new(:collaboration => collaboration, :influence => influence, :skill => skill,
                                     :activity => activity, :file => file, :issue => issue, :level => level)
  end
  
  def update_user_score(user)
    collaboration = calculate_collaboration_count(user)
    influence = calculate_influence_count(user)
    skill = calculate_skill_count(user)
    file = calculate_file(user)
    issue = calculate_issue(user)

    ##activity = calculate_activity_count(user)
    
    level = calculate_level(user)
    user.user_score.update_attributes(:collaboration => collaboration, :influence => influence, :skill => skill,
                                      :activity => activity, :file => file, :issue => issue, :level => level)
  end
  
  


end
