package main

import (
	"fmt"
	"net/smtp"
	"strings"
	"time"
)

type MailRequest struct {
	sendto  []string
	title   string
	content string
}

type MailSender struct {
	queue chan *MailRequest
}

const (
	LOOP_DELAY      = 3
	LOOP_QUEUE_SIZE = 10
	PUSH_TIMEOUT    = 3
)

func NewMailSender() *MailSender {
	return &MailSender{
		queue: make(chan *MailRequest, 100),
	}
}

func (s *MailSender) Loop() {
	timer := time.NewTimer(time.Second * LOOP_DELAY)
	timeouted := false
	for {
		list := make([]*MailRequest, 0)
		//一次取10条记录
		for i := 0; i < LOOP_QUEUE_SIZE; i++ {
			timer.Reset(time.Second * LOOP_DELAY)
			select {
			case req, ok := <-s.queue:
				timeouted = false
				timer.Stop()
				if ok {
					list = append(list, req)
				}
			case <-timer.C:
				timeouted = true
			}
			//如果不足10条也返回
			if timeouted {
				break
			}
		}
		//发送邮件
		if len(list) > 0 {
			s.Send(list)
		}
	}
}

func (s *MailSender) Send(list []*MailRequest) {
	if len(list) == 0 {
		return
	}
	//取SMTP配置
	cfg := SysCfg.GetMulti([]string{"smtp_host", "smtp_port", "smtp_user", "smtp_pwd", "smtp_sender"})
	auth := smtp.PlainAuth("", cfg["smtp_user"], cfg["smtp_pwd"], cfg["smtp_host"])
	address := fmt.Sprintf("%s:%s", cfg["smtp_host"], cfg["smtp_port"])
	//循环发送
	for _, req := range list {
		data := "From: " + cfg["smtp_user"] + "\r\nSender: " + cfg["smtp_sender"] + "\r\nTo: " + strings.Join(req.sendto, ";") + "\r\nContent-Type: text/html;charset=utf-8\r\nSubject: " + req.title + "\r\n\r\n" + req.content
		err := smtp.SendMail(address, auth, cfg["smtp_user"], req.sendto, []byte(data))
		if err != nil {
			SYSLOG("ERROR", fmt.Sprintf("邮件发送失败:%s,邮件内容如下：%s", err.Error(), data))
		}
	}
}

func (s *MailSender) Push(req *MailRequest) {
	timer := time.NewTimer(time.Second * PUSH_TIMEOUT)
	select {
	case s.queue <- req:
		timer.Stop()
	case <-timer.C:
	}
}
