package model

import (
	"regexp"
	"time"

	"github.com/jinzhu/gorm"
)

// Message - discord message
type Message struct {
	ID              string       `gorm:"primary_key" json:"id"`
	CreatedAt       time.Time    `json:"created_at"`
	UpdatedAt       time.Time    `json:"updated_at"`
	DeletedAt       *time.Time   `json:"deleted_at"`
	ChannelID       string       `json:"channel_id"`
	Content         string       `json:"content"`
	Timestamp       time.Time    `json:"timestamp"`
	EditedTimestamp time.Time    `json:"edited_timestamp"`
	MentionRoles    string       `json:"mention_roles"`
	Tts             bool         `json:"tts"`
	MentionEveryone bool         `json:"mention_everyone"`
	User            User         `json:"user"`
	UserID          string       `json:"user_id"`
	Attachments     []Attachment `json:"attachments"`
}

// MessageSave -
func MessageSave(conn *gorm.DB, m *Message) error {
	return conn.Save(m).Error
}

const urlRegexp = `https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)`

var linkedPostsCacheTimeout time.Time
var linkedPostsCache map[string]int

// MessageGet - returns all messages - must use paging
func MessageGet(conn *gorm.DB, page int) ([]Message, error) {
	messages := []Message{}
	err := conn.Offset(page*100).Limit(100).Order("timestamp desc", true).Preload("User").Find(&messages).Error
	return messages, err
}

// MessageGetLinked - get count of discord comments that contain URL's - per user
// cached for 10 minutes because there is a lot of data filtering
func MessageGetLinked(conn *gorm.DB) (map[string]int, error) {

	if linkedPostsCacheTimeout.After(time.Now().Add(-10 * time.Minute)) {
		return linkedPostsCache, nil
	}

	result := []map[string]interface{}{}
	rows, err := conn.Table("messages").
		Select("users.username, messages.content").
		Joins("join users on messages.user_id = users.id").
		Rows()

	if err != nil {
		return map[string]int{}, err
	}

	for rows.Next() {
		var username, content string
		rows.Scan(&username, &content)
		result = append(result, map[string]interface{}{
			"username": username,
			"content":  content,
		})
	}

	linkedPostsCacheTimeout = time.Now()
	linkedPostsCache = groupPosts(result)

	return linkedPostsCache, nil
}

// group posts by user and count
func groupPosts(posts []map[string]interface{}) map[string]int {

	result := map[string]int{}

	for _, p := range posts {
		match, _ := regexp.MatchString(urlRegexp, p["content"].(string))

		if match {
			if _, ok := result[p["username"].(string)]; ok {
				result[p["username"].(string)]++
			} else {
				result[p["username"].(string)] = 1
			}
		}
	}

	return result
}
