
require 'minyou/imap_helper'
module Minyou
	module MailHelper
		include PhotosHelper
		include AesHelper
		include EmailHelper
		
		def url_for(options = {})
	      Rails.application.routes.url_helpers.url_for(options)
	    end
		Expiration = 60*60*24*180

		def uniq_email(email_str)
			if email_str then
				emails = email_str.split(",")
				email_str = emails.uniq.join(",")
			end
			email_str
		end
		
		def init_mail
		  init_imap CONFIG[:mail_admin],AesHelper.decrypt(CONFIG[:mail_password])
		  init_smtp CONFIG[:mail_admin],AesHelper.decrypt(CONFIG[:mail_password])
		  @@error = {}          
		  error = @@error
		  error["421"] = "服务器未就绪"
		  error["440"] = "邮件地址错误"
		  error["445"] = "服务拒绝"
		  error["450"] = "操作未完成，邮箱不可用，可能是PTR解析错误"
		  error["451"] = "无法解析发件人地址"
		  error["452"] = "操作无法完成，系统空间不足"
		  error["454"] = "安全因素，客户端不能认证"
		  error["472"] = "DNS错误"
		  
		  error["500"] = "语法错误，未知命令"
		  error["501"] = "参数格式错误"
		  error["503"] = "错误的命令序列"
		  error["504"] = "命令参数无法实现"
		  error["505"] = "邮箱需要身份验证"
		  error["521"] = "系统配置拒绝该地址的邮件"
		  error["535"] = "系统认证出错"
		  error["550"] = "收信人邮件地址不存在"
		  error["551"] = "发送人非本地用户"
      error["552"] = "邮件超出存储空间"
		  error["553"] = "邮箱名不可用，可能是格式错误"
		  error["554"] = "无此使用者"
      error["571"] = "发件人无效"
		end
		
		def get_error code
		  e = @@error[code]
		  unless e.nil?
		    e
		  else
		    "未知的邮件服务器错误"
		  end 
		end

		def init_imap (name=nil,password=nil)

			email = name	
			pass = password

			config_hash=CONFIG[:mail_imap]
			config_hash.symbolize_keys!.merge!(:user_name=>email,:password=>pass)
			# Mail.defaults do
				# retriever_method :imap, config_hash
			# end

      IMAPHelper.init_imap_center config_hash
      @fail_uids = Set.new #放置一个出现异常的邮件的UID 当邮件内容第一次出现异常进入这个set 这是为了让出错的邮件有一次重试的机会
		end

		def init_smtp (name=nil,password=nil)
			email=name
			pass=password
			config_hash=CONFIG[:mail_smtp]
			config_hash.symbolize_keys!.merge!(:user_name=>email,:password=>pass)
			#p config_hash
			Mail.defaults do
				delivery_method :smtp, config_hash
			end
		end

		
		def receive_new_email
			begin
			  #puts "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
				#Rails.logger.info "start receive mail.time:#{Time.now}"
				#init_imap CONFIG[:mail_admin],AesHelper.decrypt(CONFIG[:mail_password])
				#todo for develop debug
				#emails=Mail.find({:delete_after_find=>true,:count=>20})
				#emails=Mail.find(keys: ['NOT','SEEN'])
				#emails =  [Mail.find(:what => :first, :count => 1, :order => :asc)]
        emails=IMAPHelper.receive_mail_from_server_by_uid
				error_uids = []#出了错误的邮件的uid 注意这里要使用UID 因为可能做过删除老邮件操作而造成 seqno发生了变化
				Rails.logger.info "receive mail count ： #{emails.size}"
				emails.each do|email|
				  m_mail = nil
				  mail_obj = nil
				  # begin
				    if email.class.name == 'Minyou::Email'
				      m_mail = email
				      mail_obj = Minyou::Email.find_by_id m_mail.id #search email is or not exist
				    else
				      m_mail=Minyou::Email.new(email)
				      mail_obj = Minyou::Email.find_by_id m_mail.id #search email is or not exist
				      $mail_redis.setex("mail:#{m_mail.id}:object",Expiration,Marshal.dump(m_mail))
				    end
  					
  					users=m_mail.to
  
  					users.concat m_mail.cc if m_mail.cc.present?
  					users.concat m_mail.bcc if m_mail.bcc.present?
  					users=users.uniq.delete_if {|x| (! x.end_with? CONFIG[:mail_domain])} 
  
  					valid_emails = []
  					users.each do|email|
  						next if mail_obj and email == m_mail.from.first
  						valid_emails << email
  					end
  					UserEmailProcessor.perform_async valid_emails, m_mail.id
					# rescue Exception =>e
					  # #如果某个邮件出现异常 则吧这个邮件设置成未读 这是为了修正一个不是每次都出的 图片操作的异常而做的补救
					  # uid = email.UID
					  # if @fail_uids.include? uid.to_s
					    # #这说明已经失败过一次
					    # Rails.logger.error "email #{email.subject} id: #{email.UID} 接收已经失败过一次，因此将永久放弃"
					    # Rails.logger.error "receive email  error:#{e.message}\n\n#{e.backtrace.join("\n")}"
					  # else
					    # #第一次失败 再给一次机会
					    # error_uids << uid
					    # @fail_uids.add uid.to_s
					    # Rails.logger.error "email #{email.subject} id: #{email.UID} 接收失败，因此将重试接收一次"
					    # Rails.logger.error "receive email  error:#{e.message}\n\n#{e.backtrace.join("\n")}"
					  # end
          # ensure
            # @fail_uids.delete uid.to_s
          # end
				end
			rescue Exception =>e
				Rails.logger.error "receive email  error:#{e.message}\n\n#{e.backtrace.join("\n")}"
			ensure
			end
		end

	    def convert_users users=[],user_address=[]
	    	return [] if users.nil?
	    	users.each_with_index.map do |mail,idx|
	    		 account=Account.find_by_email mail
				if account.nil? then
					_address=user_address[idx]
					if(_address.index(" <")) then
						mail_name=_address.split(" <").first.gsub(/^"|"$/,"")
					else
						mail_name=_address.split("@").first
					end
					email_postfix = mail.split("@").second
					identify = "default"
					identify = email_postfix.split(".").first if image_emails.include? email_postfix
					{:name=>mail_name,:email=>mail,:type=>"address", :avatar_url=>"/photos/email_#{identify}"}
				else
					user=account.home_user
					if user.nil?
						Rails.logger.error "账户email为 #{mail}的账户无法获取home_user 因此有些返回信息会缺失"
						{:name=>"",:dept=>"",:title=>"",:email=>mail,:id=>"",:avatar_url=>"/photos/#{none}",:type=>"user"}
					else
					  user_info = UserInfo.find_cached_by_user_id(user.id)
				    full_dept=user_info.department
				    if full_dept then
					    deptFrags=full_dept.split("/")
					    #Need remove root,if it is not root department
					    department_name = full_dept.sub("#{deptFrags.first}/","").split("/").last(2).join("/") 
					  end
					  photo = Photo.find_cached_by_id user.image_id
					  photo_id =( photo && photo.image_fingerprint)||"none"
					  {:name=>user.name,:dept=>department_name,:title=>user_info.title,:email=>mail,:id=>user.id,:avatar_url=>"/photos/#{photo_id}",:type=>"user"}
				   end
				  end
	    	end

	    end

	    def mail_to_json mail
	      mail_json=Hash.new
          mail_json[:id]=mail.id
          mail_json[:subject]=mail.subject
          mail_json[:content]=mail.content
          mail_json[:attachments]=mail.attachments
          mail_json[:atts_size]=mail.attachments.size
          mail_json[:sender]=convert_users(mail.from,mail.from_addrs).first
          mail_json[:to]=convert_users  mail.to ,mail.to_addrs
          mail_json[:cc]=convert_users mail.cc,mail.cc_addrs
          mail_json[:bcc]=convert_users mail.bcc,mail.bcc_addrs
          mail_json[:date]=mail.date
          mail_json[:short_content] = mail.short_content
          mail_json
	    end
	    
	    def fetchAttachment attach,att_path,mail_id
	      uid = attach.UID
	      body_id = attach.body_id
	      #init_imap CONFIG[:mail_admin],AesHelper.decrypt(CONFIG[:mail_password])
	      IMAPHelper.fetchAttachment uid,body_id,att_path,mail_id
	    end
	    
	    def support_idle?
	      #init_imap CONFIG[:mail_admin],AesHelper.decrypt(CONFIG[:mail_password])
	      IMAPHelper.support_idle?
	    end
	    
	    def mail_idle
	      IMAPHelper.mail_idle do
	        receive_new_email
	      end
	    end
	end

end