package email

import (
	"bytes"
	"crypto/tls"
	"html/template"
	"strings"
	"sync"

	"corelab.mkcl.org/MKCLOS/coredevelopmentplatform/corepkgv2/errormdl"
	"corelab.mkcl.org/MKCLOS/coredevelopmentplatform/corepkgv2/loggermdl"
	"corelab.mkcl.org/MKCLOS/coredevelopmentplatform/corepkgv2/utiliymdl/guidmdl"
	gomail "gopkg.in/gomail.v2"
)

var instances map[string]EmailConfig
var onceMutex sync.Once
var defaultHost string

// InitUsingJSON initializes Email Connections for give JSON data
func InitUsingJSON(configs []EmailConfig) {
	onceMutex.Do(func() {
		instances = make(map[string]EmailConfig)
		for _, config := range configs {
			instances[config.HostName] = config
			if config.IsDefault {
				defaultHost = config.HostName
			}
		}
	})
}

// SendMailFromSLS -send email
func (email *Email) SendMailFromSLS(hostName string) error {
	config := EmailConfig{}
	if hostName == "" {
		tmp, ok := instances[defaultHost]
		if !ok {
			loggermdl.LogError("Host not found: " + hostName)
			return errormdl.Wrap("Host not found: " + hostName)
		}
		config = tmp
	} else {
		tmp, ok := instances[hostName]
		if !ok {
			loggermdl.LogError("Host not found: " + hostName)
			return errormdl.Wrap("Host not found: " + hostName)
		}
		config = tmp
	}

	domain, domainErr := getSenderDomain(email.from)
	if domainErr != nil {
		loggermdl.LogError("error getting domain address: ", domainErr)
		return domainErr
	}

	message := gomail.NewMessage()
	message.SetHeader("From", email.from)
	message.SetHeader("To", email.to...)
	message.SetHeader("Reply-To", email.replyTo)
	message.SetHeader("Cc", email.cc...)
	message.SetHeader("Bcc", email.bcc...)
	message.SetHeader("Subject", email.subject)
	message.SetHeader("Message-ID", getMSGIDHeader(domain, guidmdl.GetGUID()))
	if len(strings.TrimSpace(email.plainBody)) == 0 {
		message.SetBody("text/html", email.body)
	} else {
		message.SetBody("text/plain", email.plainBody)
		message.AddAlternative("text/html", email.body)
	}

	for _, attachment := range email.attachments {
		message.Attach(attachment) // attach whatever you want
	}
	dialer := gomail.Dialer{Host: config.Server, Port: config.Port, Username: config.Username, Password: config.Password, SSL: config.SSL}
	dialer.TLSConfig = &tls.Config{InsecureSkipVerify: !config.SSL}
	if err := dialer.DialAndSend(message); errormdl.CheckErr1(err) != nil {
		loggermdl.LogError("error occured while calling Send(): ", errormdl.CheckErr1(err))
		return err
	}
	return nil
}

// // ParseTemplateText -ParseTemplateText
// func (email *Email) ParseTemplateText(templateText string, templateData interface{}) error {
// 	tmplt, err := raymond.Parse(templateText)
// 	if errormdl.CheckErr(err) != nil {
// 		loggermdl.LogError("error occured while calling parseTemplateText: ", errormdl.CheckErr(err))
// 		return err
// 	}
// 	emailbody, err := tmplt.Exec(templateData)
// 	if errormdl.CheckErr1(err) != nil {
// 		loggermdl.LogError("error occured while calling parseTemplateText: ", errormdl.CheckErr1(err))
// 		return err
// 	}
// 	email.body = emailbody
// 	return nil
// }

// ParseTemplateText - ParseTemplateText
func (email *Email) ParseTemplateText(templateFileText string, templateData interface{}) error {

	tmp := template.Must(template.New("email").Parse(templateFileText))

	// tmplt, err := template.ParseGlob(templateFileText)
	// if errormdl.CheckErr(err) != nil {
	// 	loggermdl.LogError("error occured while calling parseTemplateFile: ", errormdl.CheckErr(err))
	// 	return err
	// }
	buffer := new(bytes.Buffer)
	err := tmp.Execute(buffer, templateData)
	if err != nil {
		loggermdl.LogError(err)
		return err
	}
	// if err = tmplt.Execute(buffer, templateData); errormdl.CheckErr1(err) != nil {
	// 	loggermdl.LogError("error occured while calling parseTemplateFile: ", errormdl.CheckErr1(err))
	// 	return err
	// }
	email.body = buffer.String()
	return nil
}

// ParsePlainText - ParsePlainText
func (email *Email) ParsePlainText(templateFileText string, templateData interface{}) error {

	tmp := template.Must(template.New("email").Parse(templateFileText))

	buffer := new(bytes.Buffer)
	err := tmp.Execute(buffer, templateData)
	if err != nil {
		loggermdl.LogError(err)
		return err
	}

	email.plainBody = buffer.String()
	return nil
}