# 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 Redmine
  module Acts
    module Attachable
      def self.included(base)
        base.extend ClassMethods
      end

      module ClassMethods
        def acts_as_attachable(options = {})
          cattr_accessor :attachable_options
          self.attachable_options = {}
          attachable_options[:view_permission] = options.delete(:view_permission) || "view_#{self.name.pluralize.underscore}".to_sym
          attachable_options[:delete_permission] = options.delete(:delete_permission) || "edit_#{self.name.pluralize.underscore}".to_sym

          has_many :attachments, options.merge(:as => :container,
                                               :order => "#{Attachment.table_name}.created_on ASC, #{Attachment.table_name}.id ASC",
                                               :dependent => :destroy)
          send :include, Redmine::Acts::Attachable::InstanceMethods
          before_save :attach_saved_attachments
        end
      end

      module InstanceMethods
        def self.included(base)
          base.extend ClassMethods
        end

        def attachments_visible?(user=User.current)
          if self.respond_to?(:project)
            (respond_to?(:visible?) ? visible?(user) : true) &&
                user.allowed_to?(self.class.attachable_options[:view_permission], self.project)
          elsif self.is_a?(Course)
            (respond_to?(:visible?) ? visible?(user) : true) &&
              user.allowed_to?(self.class.attachable_options[:view_permission], self)
          else
            return true
          end

        end

        def attachments_deletable?(user=User.current)
          if (self.has_attribute?(:course) ||self.has_attribute?(:course_id)) && self.course
            #默认给予删除自己上传的附件的权限
            (respond_to?(:visible?) ? visible?(user) : true) &&
                (user.allowed_to?(self.class.attachable_options[:delete_permission], self.course) || (self.has_attribute?(:author_id) && self.author == user))
          else
            #默认给予删除自己上传的附件的权限
            (respond_to?(:visible?) ? visible?(user) : true) &&
                (user.allowed_to?(self.class.attachable_options[:delete_permission], self.project) || (self.has_attribute?(:author_id) && self.author == user))
          end
        end

        def saved_attachments
          @saved_attachments ||= []
        end

        def unsaved_attachments
          @unsaved_attachments ||= []
        end

        # 设置资源文件的公开属性
        # add by nwb
        def set_attachment_public(res)
          # 公开的资源判断他的父级的公开属性
          if res.is_public
            if( (self.class.to_s=="Project" && self.is_public == false) ||
                (self.has_attribute?(:project) && self.project && self.project.is_public == false) ||
                (self.has_attribute?(:board) && self.board.project && self.board.project.is_public == false) ||
                (self.class.to_s=="HomeworkAttach" && self.bid.reward_type == 3) ||
                (self.class.to_s=="Course" && self.is_public == false) ||
                (self.has_attribute?(:course) && self.course && self.course.is_public == false) ||
                (self.has_attribute?(:board) && self.board.course && self.board.course.is_public == false)
            )
              res.is_public = false
            end
          end
        end

        def save_attachmentsex(attachments, author=User.current,attachment_type)
          @curattachment_type = attachment_type
          result = save_attachments(attachments,author)
          result
        end

        def save_attachmentsex_public(attachments, author=User.current,attachment_type, is_public)
          @curattachment_type = attachment_type
          @is_public = true
          result = save_attachments(attachments,author)
          result
        end

        def save_attachments(attachments, author=User.current)
          # 清除临时文件
          if attachments
            tempAttach = attachments[:dummy]
            if  tempAttach && tempAttach[:file]
              attachments.delete(:dummy)
            end
          end

          if attachments.is_a?(Hash)
            attachments = attachments.stringify_keys
            attachments = attachments.to_a.sort {|a, b|
              if a.first.to_i > 0 && b.first.to_i > 0
                a.first.to_i <=> b.first.to_i
              elsif a.first.to_i > 0
                1
              elsif b.first.to_i > 0
                -1
              else
                a.first <=> b.first
              end
            }
            attachments = attachments.map(&:last)
          end
          if attachments.is_a?(Array)
            attachments.each do |attachment|
              if attachment.is_a?(Hash)
                a = nil
                file = attachment['file']
                token = attachment['token']
                t = file && file.size > 0
                if file && file.size > 0
                    a = Attachment.create(:file => file, :author => author)
                elsif token
                  # 通过token值找到对应的attachment
                  a = Attachment.find_by_token_only(token)
                  if a
                    a.filename = attachment['filename'] unless attachment['filename'].blank?
                    a.content_type = attachment['content_type']
                  end
                end
              end

              if a && !attachment['is_public_checkbox']
                if @is_public
                  a.is_public = true
                else
                  a.is_public = false
                end
              elsif a && attachment['is_public_checkbox']
                a.is_public = true
              end
              set_attachment_public(a) if a
              next unless a
              a.description = attachment['description'].to_s.strip
              a.attachtype = @curattachment_type
              if a.new_record?
                unsaved_attachments << a
              else
                saved_attachments << a
              end
            end
          end
          {:files => saved_attachments, :unsaved => unsaved_attachments}
        end

        def attach_saved_attachments
          saved_attachments.each do |attachment|
            self.attachments << attachment
          end
        end

        module ClassMethods
        end
      end
    end
  end
end
